<?php
// Prevent direct access
if (count(get_included_files()) === 1) {
    http_response_code(403);
    exit('Forbidden');
}

require_once dirname(__DIR__) . '/services/agent_service.php';

// --- CORS (widget runs on the SMB's domain; the public key is the gate) ---
$origin = $_SERVER['HTTP_ORIGIN'] ?? '*';
header('Access-Control-Allow-Origin: ' . $origin);
header('Vary: Origin');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

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

/** Send a JSON response and stop. */
function json_out(int $code, array $payload): void {
    http_response_code($code);
    echo json_encode($payload);
    exit;
}

/** RFC 4122 v4 UUID. */
function uuid_v4(): string {
    $data = random_bytes(16);
    $data[6] = chr((ord($data[6]) & 0x0f) | 0x40);
    $data[8] = chr((ord($data[8]) & 0x3f) | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

// --- Parse JSON body ---
$raw = file_get_contents('php://input');
$input = json_decode($raw, true);
if (!is_array($input)) {
    json_out(400, ['error' => 'Invalid JSON body']);
}

$key = trim((string) ($input['key'] ?? ''));
$visitorId = trim((string) ($input['visitorId'] ?? ''));
$message = trim((string) ($input['message'] ?? ''));

if ($key === '') {
    json_out(400, ['error' => 'Missing embed key']);
}
if ($message === '') {
    json_out(400, ['error' => 'Empty message']);
}
if (mb_strlen($message) > 2000) {
    json_out(400, ['error' => 'Message too long']);
}

$db = DB::connect();

// --- Resolve tenant by public embed key ---
$stmt = $db->prepare("SELECT * FROM tenants WHERE web_public_key = :key AND deleted_at IS NULL LIMIT 1");
$stmt->execute([':key' => $key]);
$tenant = $stmt->fetch();
if (!$tenant) {
    json_out(403, ['error' => 'Unknown embed key']);
}
$tenant['_channel'] = 'web';
$tenantId = (int) $tenant['id'];

// --- Resolve or create the web visitor (contact) ---
$contactId = null;
if ($visitorId !== '') {
    $stmt = $db->prepare("SELECT id FROM contacts WHERE tenant_id = :tenant_id AND web_visitor_id = :visitor LIMIT 1");
    $stmt->execute([':tenant_id' => $tenantId, ':visitor' => $visitorId]);
    $row = $stmt->fetch();
    if ($row) {
        $contactId = (int) $row['id'];
    }
}
if ($contactId === null) {
    $visitorId = uuid_v4();
    $stmt = $db->prepare(
        "INSERT INTO contacts (tenant_id, name, web_visitor_id, channel)
         VALUES (:tenant_id, 'Visitante web', :visitor, 'web')"
    );
    $stmt->execute([':tenant_id' => $tenantId, ':visitor' => $visitorId]);
    $contactId = (int) $db->lastInsertId();
}

$conversationId = AgentService::findOrCreateConversation($db, $tenantId, $contactId, 'web');

// --- Rate-limit: cap inbound messages per conversation in a 60s window ---
$stmt = $db->prepare(
    "SELECT COUNT(*) AS n FROM messages
     WHERE conversation_id = :cid AND direction = 'inbound'
       AND created_at > (NOW() - INTERVAL 60 SECOND)"
);
$stmt->execute([':cid' => $conversationId]);
if ((int) $stmt->fetch()['n'] >= 15) {
    json_out(429, ['error' => 'Too many messages, slow down', 'visitorId' => $visitorId]);
}

AgentService::persistInbound($db, $tenantId, $conversationId, $message);
AgentService::refreshWindow($db, $conversationId);

// --- Build context, call Gemini, persist reply + agent_log ---
try {
    $result = AgentService::handleMessage($db, $tenant, $conversationId, $contactId);
    json_out(200, [
        'reply'          => $result['text'],
        'conversationId' => $conversationId,
        'visitorId'      => $visitorId,
        'options'        => $result['options'] ?? [],
        'accion'         => $result['accion'] ?? null,
    ]);
} catch (Throwable $e) {
    error_log("Web agent generation failed: " . $e->getMessage());
    AgentService::logError($db, $tenantId, 'web_error', $e);
    json_out(500, [
        'error' => 'temporary_failure',
        'reply' => 'Estoy teniendo un problema técnico. Por favor intentá de nuevo en un momento.',
        'visitorId' => $visitorId,
    ]);
}
