<?php
/**
 * Colex's real AI provider integration — the one place in the app that
 * knows how to call Anthropic's API. Extracted from api/colex/chat.php
 * (2026-08-10, Alignex→Colex rebrand cleanup) so every Colex-branded
 * feature that needs real model reasoning (chat, and now Strategy
 * Builder's Polish/AI-First checklist assist) shares one authenticated,
 * server-side call path instead of each maintaining its own copy — or,
 * as strategy.php's old callAlignex() did, calling the provider directly
 * from client-side JS with no API key at all (broken on every call, and
 * the wrong place for a real key to ever live even if it worked).
 */

if (!function_exists('getColexApiKey')) {
    /**
     * Reads the Anthropic API key from config. Define ANTHROPIC_API_KEY as
     * a constant in config/config.php, or set it as an environment
     * variable — neither is wired up by default. Until one is present,
     * callAnthropicAPI() below returns null and callers fall back to
     * their own degraded-mode behavior.
     */
    function getColexApiKey() {
        if (defined('ANTHROPIC_API_KEY') && ANTHROPIC_API_KEY) {
            return ANTHROPIC_API_KEY;
        }
        $env = getenv('ANTHROPIC_API_KEY');
        return $env !== false && $env !== '' ? $env : null;
    }
}

/**
 * The model string to call. Current Sonnet 5 model ID — worth a quick
 * sanity check against whatever model your Anthropic account actually
 * has access to before relying on it in production, since model
 * availability can change independently of what's current at the time
 * this was written.
 */
if (!defined('COLEX_MODEL')) {
    define('COLEX_MODEL', 'claude-sonnet-5');
}

if (!function_exists('callAnthropicAPI')) {
    /**
     * Calls the real Anthropic Messages API. Returns ['text' => ..., 'usage' =>
     * ...] on success — `usage` is the raw, provider-shaped usage object
     * exactly as Anthropic returned it (input_tokens/output_tokens/etc.),
     * untouched. This function does no unit conversion and knows nothing
     * about allowances — obtaining the raw metadata is as far as the provider
     * integration's job goes; converting it happens only in
     * usage-engine.php's conversion layer (Rule 1).
     *
     * Returns null on any failure (missing key, curl error, non-200,
     * unexpected shape) — null is the caller's signal to fall back to
     * whatever degraded-mode behavior fits that caller (chat.php's
     * rule-based engine; assist.php's honest "unavailable" error) instead
     * of trying to fabricate a "reasoned" answer without an actual model
     * behind it.
     *
     * @param int $maxTokens Optional, defaults to 1024 (chat's existing
     *        behavior, unchanged). Structured-output callers that expect a
     *        larger JSON payload back (e.g. a full checklist decomposition)
     *        can raise this.
     */
    function callAnthropicAPI($systemPrompt, $messages, $maxTokens = 1024) {
        $apiKey = getColexApiKey();
        if (!$apiKey) {
            return null;
        }

        if (!function_exists('curl_init')) {
            error_log("[Colex] curl extension not available — cannot call Anthropic API");
            return null;
        }

        $payload = [
            'model' => COLEX_MODEL,
            'max_tokens' => $maxTokens,
            'system' => $systemPrompt,
            'messages' => $messages,
        ];

        $ch = curl_init('https://api.anthropic.com/v1/messages');
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'x-api-key: ' . $apiKey,
                'anthropic-version: 2023-06-01',
            ],
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_TIMEOUT => 30,
        ]);

        $raw = curl_exec($ch);
        $curlErr = curl_error($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($curlErr) {
            error_log("[Colex] Anthropic API curl error: {$curlErr}");
            return null;
        }
        if ($httpCode !== 200) {
            error_log("[Colex] Anthropic API returned HTTP {$httpCode}: " . substr($raw, 0, 500));
            return null;
        }

        $data = json_decode($raw, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("[Colex] Anthropic API response was not valid JSON");
            return null;
        }

        $text = '';
        foreach (($data['content'] ?? []) as $block) {
            if (($block['type'] ?? '') === 'text') {
                $text .= $block['text'];
            }
        }

        if ($text === '') {
            return null;
        }

        return [
            'text' => $text,
            'usage' => $data['usage'] ?? [],
        ];
    }
}
