<?php
/**
 * Colex AI — Strategy Builder Assist Endpoint
 *
 * Real, server-side, authenticated replacement for the old "Alignex"
 * client-side integration (public/strategy.php's callAlignex(), deleted
 * 2026-08-10 as part of the Alignex→Colex rebrand cleanup) — that
 * function called Anthropic's API directly from browser JS with no API
 * key anywhere in the request, so it failed every single time it was
 * invoked. This is the same capability (checklist "Polish" and
 * "AI-First" decomposition), routed through the same authenticated,
 * server-side provider integration Colex chat already uses correctly
 * (src/ColexProvider.php), under the real Colex brand throughout.
 *
 * POST /api/colex/assist
 * Body: { "task": "polish", "items": [{id, category, raw_text}, ...] }
 *   or  { "task": "ai_first", "rules_text": "..." }
 *
 * Returns: { "success": true, "items": [...] }                (polish)
 *      or: { "success": true, "checklist_items": [...], "edge": {...} }  (ai_first)
 *      or: { "success": false, "error": "..." }
 */

// Ensure this file is accessed through the router
if (!isset($auth) || !isset($db)) {
    http_response_code(500);
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'error' => 'Direct access not permitted.']);
    exit;
}

// Ensure user is authenticated
if (!$auth->isLoggedIn()) {
    http_response_code(401);
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'error' => 'Authentication required']);
    exit;
}

header('Content-Type: application/json');

require_once __DIR__ . '/usage-engine.php';
require_once __DIR__ . '/../../src/ColexProvider.php';

$userId = $auth->getUserId();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'error' => 'Method not allowed']);
    exit;
}

$input = json_decode(file_get_contents('php://input'), true);
$task = isset($input['task']) ? $input['task'] : '';

if (!in_array($task, ['polish', 'ai_first'], true)) {
    echo json_encode(['success' => false, 'error' => 'Unknown or missing task']);
    exit;
}

// Same allowance gate chat.php uses (Rule 4) — checked before touching
// the provider at all, so an exhausted user can't spend a call here
// even if the UI's own tier/disabled-state check were bypassed.
list($canSend, $allowanceStatus) = canSendColexMessage($db, $userId);
if (!$canSend) {
    http_response_code(403);
    echo json_encode([
        'success' => false,
        'error' => 'allowance_exhausted',
        'usage_status' => formatAllowanceForFrontend($allowanceStatus)
    ]);
    exit;
}

// Build the system/user prompt pair — the exact same instructions the
// old callAlignex() call sites used (runPolish()/runAiFirst() in
// public/strategy.php), carried over verbatim so no real behavior is
// lost in the move, just where it lives and how it authenticates.
if ($task === 'polish') {
    $items = isset($input['items']) && is_array($input['items']) ? $input['items'] : [];
    if (empty($items)) {
        echo json_encode(['success' => false, 'error' => 'No checklist items provided']);
        exit;
    }
    $systemPrompt = "Reword the trader's OWN checklist items. NEVER invent. Return JSON.";
    $userPrompt = json_encode(array_map(function ($i) {
        return [
            'id' => $i['id'] ?? '',
            'category' => $i['category'] ?? '',
            'raw_text' => $i['raw_text'] ?? '',
        ];
    }, $items));
} else {
    $rulesText = isset($input['rules_text']) ? trim((string)$input['rules_text']) : '';
    if ($rulesText === '') {
        echo json_encode(['success' => false, 'error' => 'No rules text provided']);
        exit;
    }
    $systemPrompt = "Decompose trader's rules into checklist. NEVER invent. Return JSON.";
    $userPrompt = "Rules:\n" . $rulesText;
}

// max_tokens raised from chat.php's 1024 default to 1500 (matching the
// old client-side call's own value) — a full checklist decomposition
// plus edge parameters can run longer than a normal chat reply.
$llmResult = callAnthropicAPI($systemPrompt, [['role' => 'user', 'content' => $userPrompt]], 1500);

if ($llmResult === null) {
    echo json_encode(['success' => false, 'error' => 'Colex is unavailable right now. Please try again shortly.']);
    exit;
}

// The model may wrap its JSON in a markdown code fence — same stripping
// the old client-side callAlignex() did before JSON.parse().
$text = trim(preg_replace('/```json|```/', '', $llmResult['text']));
$parsed = json_decode($text, true);

if (json_last_error() !== JSON_ERROR_NONE || !is_array($parsed)) {
    error_log("[Colex Assist] Model response was not valid JSON for task='{$task}': " . substr($text, 0, 500));
    echo json_encode(['success' => false, 'error' => 'Colex returned an unexpected response. Please try again.']);
    exit;
}

// 'strategy_assist' — a real, new feature tag (Rule 7, same free-form
// convention recordColexUsage()'s own doc comment already documents:
// new capabilities just start passing a new tag, no schema change).
recordColexUsage($db, $userId, 'anthropic', $llmResult['usage'], 'strategy_assist');

$response = ['success' => true];
if ($task === 'polish') {
    $response['items'] = $parsed['items'] ?? [];
} else {
    $response['checklist_items'] = $parsed['checklist_items'] ?? [];
    $response['edge'] = $parsed['edge'] ?? [];
}
echo json_encode($response);
