<?php

/**
 * ============================================================
 *  AutonomousSystem.php
 *  Bot de comentarios y Messenger — Versión unificada
 * ============================================================
 */


// ============================================================
//  TEMPLATES DE MENSAJES DEL BOT
// ============================================================

function botTemplate(string $key, array $vars = []): string
{
    $emojis = ['✅', '🎉', '👏', '🛒', '⭐', '💚', '🙌', '👍', '🤩', '💫', '🔥', '❤️'];
    $e = $emojis[array_rand($emojis)];

    $templates = [
        'added_to_cart' => [
            "Adicionado ao carrinho: {product} x{qty} {$e}",
            "Pronto! {product} x{qty} reservado {$e}",
            "{product} x{qty} já está no teu carrinho {$e}",
            "Feito! {product} x{qty} guardado no carrinho {$e}",
            "Reservado: {product} x{qty} {$e}",
            "Tudo certo! {product} x{qty} adicionado {$e}",
            "{product} x{qty} confirmado no carrinho {$e}",
            "Boa escolha! {product} x{qty} reservado {$e}",
        ],
        'not_found' => [
            "Não encontrei nenhum produto com a referência \"{ref}\" 🔍",
            "Referência \"{ref}\" não encontrada 🔍",
            "Não consegui encontrar \"{ref}\", verifica a referência 🔍",
            "A referência \"{ref}\" não existe no catálogo 🔍",
            "Hmm, \"{ref}\" não aparece nos nossos produtos 🔍",
            "Não temos nenhum artigo com ref \"{ref}\" 🔍",
        ],
        'need_attributes' => [
            "Para o produto \"{product}\" preciso que indiques: {need} 📝",
            "Falta indicar {need} para \"{product}\" 📝",
            "\"{product}\" tem variações, indica: {need} 📝",
            "Qual {need} pretendes para \"{product}\"? 📝",
            "Indica {need} para podermos reservar \"{product}\" 📝",
            "\"{product}\" está disponível em várias opções, diz-nos: {need} 📝",
        ],
        'out_of_stock' => [
            "Lamentamos, mas \"{product}\" (ref {ref}) está sem stock 😔",
            "\"{product}\" (ref {ref}) esgotado de momento 😔",
            "Sem stock para \"{product}\" (ref {ref}) 😔",
            "De momento \"{product}\" (ref {ref}) não está disponível 😔",
            "\"{product}\" (ref {ref}) ficou sem stock, desculpa 😔",
            "Infelizmente \"{product}\" (ref {ref}) já esgotou 😔",
        ],
        'already_in_cart' => [
            "Já tens \"{product}\" no carrinho ({qty} unidade(s)) {$e}\nEste artigo não foi adicionado novamente.\nSe quiseres cancelar, escreve: cancelar ref {sku}",
            "\"{product}\" já está no teu carrinho com {qty} unidade(s) {$e}\nNão foi adicionado outra vez.\nPara cancelar: cancelar ref {sku}",
            "Este artigo já foi reservado! Tens {qty} unidade(s) de \"{product}\" {$e}\nPara cancelar escreve: cancelar ref {sku}",
            "Já tinhas reservado \"{product}\" ({qty} un.) {$e}\nNão adicionámos novamente.\nCancelar? Escreve: cancelar ref {sku}",
            "\"{product}\" já consta no teu carrinho com {qty} un. {$e}\nSe pretenderes cancelar: cancelar ref {sku}",
            "Atenção, \"{product}\" já está reservado ({qty} un.) {$e}\nPara remover: cancelar ref {sku}",
        ],
        'confirm_duplicate' => [
            "Já adicionaste este artigo ao carrinho.\nPretendes adicionar mais {reqQty} unidades?\nPassarás a ter {totalQty} unidades deste artigo.\nResponde com «confirmar» a este comentário para continuar.",
            "Este artigo já está no carrinho.\nQueres juntar mais {reqQty}? Ficarás com {totalQty} no total.\nEscreve «confirmar» para continuar.",
            "Já tens este produto reservado.\nAdicionar mais {reqQty}? Total ficará em {totalQty} unidades.\nResponde «confirmar» para avançar.",
            "Este artigo já foi adicionado antes.\nQueres somar mais {reqQty} unidades? Terás {totalQty} no total.\nDiz «confirmar» para prosseguir.",
            "Produto já no carrinho! Somar +{reqQty} unidades?\nFicarás com {totalQty} no total.\nEscreve «confirmar» para confirmar.",
            "Vimos que já reservaste este artigo.\nPretendes adicionar +{reqQty}? Total: {totalQty} unidades.\nResponde «confirmar».",
        ],
        'missing_ref' => [
            "Parece que queres encomendar, mas falta a palavra \"ref\".\nEscreve assim: ref {ref}",
            "Para encomendar escreve: ref {ref} 📝",
            "Queres reservar? Escreve: ref {ref} 📝",
            "Para adicionar ao carrinho indica: ref {ref} 📝",
            "Falta a referência! Experimenta escrever: ref {ref} 📝",
            "Quase lá! Escreve assim para reservar: ref {ref} 📝",
        ],
        'cancel_not_found_product' => [
            "Não encontrei nenhum produto com referência \"{ref}\" 🔍",
            "Referência \"{ref}\" não encontrada para cancelar 🔍",
            "Não existe nenhum artigo com ref \"{ref}\" 🔍",
            "Hmm, a ref \"{ref}\" não corresponde a nenhum produto 🔍",
            "Verifica a referência, \"{ref}\" não foi encontrada 🔍",
            "Não consegui localizar \"{ref}\" nos produtos 🔍",
        ],
        'cancel_need_attributes' => [
            "Para cancelar \"{product}\" preciso que indiques: {need} 📝",
            "Qual {need} de \"{product}\" queres cancelar? 📝",
            "\"{product}\" tem variações, indica {need} para cancelar 📝",
            "Diz-nos {need} para podermos cancelar \"{product}\" 📝",
            "Preciso saber {need} para remover \"{product}\" do carrinho 📝",
            "Indica {need} de \"{product}\" que pretendes cancelar 📝",
        ],
        'cancel_no_cart' => [
            "Não encontrei nenhum carrinho 🛒",
            "Ainda não tens carrinho criado 🛒",
            "Não tens nenhum carrinho ativo de momento 🛒",
            "Parece que ainda não reservaste nada 🛒",
            "Não há nenhum carrinho associado a ti 🛒",
            "Sem carrinho para cancelar 🛒",
        ],
        'cancel_not_in_cart' => [
            "Não encontrei esse produto no teu carrinho 🔍",
            "Esse produto não está no teu carrinho 🔍",
            "Esse artigo não consta no teu carrinho 🔍",
            "Não tens esse produto reservado 🔍",
            "Esse produto não foi encontrado no teu carrinho 🔍",
            "Hmm, não tens esse artigo no carrinho 🔍",
        ],
        'cart_empty' => [
            "O teu carrinho está vazio 🛒",
            "Ainda não tens artigos no carrinho 🛒",
            "Nenhum artigo reservado de momento 🛒",
            "O carrinho está vazio, começa a reservar! 🛒",
            "Sem artigos no carrinho por agora 🛒",
            "Ainda não adicionaste nada ao carrinho 🛒",
        ],
        'confirmed_qty' => [
            "Confirmado! Agora tens {totalQty} unidade(s) deste artigo no carrinho {$e}",
            "Feito! Atualizado para {totalQty} unidade(s) no carrinho {$e}",
            "Pronto! Ficaste com {totalQty} unidade(s) deste artigo {$e}",
            "Tudo certo! {totalQty} unidade(s) no teu carrinho agora {$e}",
            "Atualizado com sucesso! Total: {totalQty} unidade(s) {$e}",
            "Quantidade atualizada para {totalQty} unidade(s) {$e}",
        ],
        'no_pending_confirm' => [
            "Não encontrei nenhum pedido pendente para confirmar 🔍",
            "Não há nenhuma confirmação pendente 🔍",
            "Nenhum pedido à espera de confirmação 🔍",
            "Não tens nada pendente para confirmar 🔍",
            "Sem pedidos pendentes de momento 🔍",
            "Não existe nenhuma confirmação em espera 🔍",
        ],
        'not_enough_stock' => [
            "Lamentamos, mas apenas restam {stock} unidade(s) deste artigo 😔",
            "Só temos {stock} unidade(s) disponíveis deste artigo 😔",
            "Stock insuficiente, restam apenas {stock} unidade(s) 😔",
            "De momento só há {stock} unidade(s) em stock 😔",
            "Infelizmente só restam {stock} unidade(s) 😔",
            "Disponíveis apenas {stock} unidade(s) deste artigo 😔",
        ],
        'update_not_found' => [
            "Não encontrei nenhum registo para atualizar 🔍",
            "Nenhum registo encontrado para atualizar 🔍",
            "Não foi possível localizar o registo 🔍",
            "Sem registo encontrado para esta atualização 🔍",
            "Não existe registo para atualizar 🔍",
            "Registo não encontrado 🔍",
        ],
    ];

    if (!isset($templates[$key])) {
        return $key;
    }

    $msg = $templates[$key][array_rand($templates[$key])];

    foreach ($vars as $k => $v) {
        $msg = str_replace('{' . $k . '}', $v, $msg);
    }

    return $msg;
}

// ============================================================
//  CAPA DE ABSTRACCIÓN DE RESPUESTA
// ============================================================

function botReply(array $replyContext, string $message)
{
    if ($replyContext['channel'] === 'messenger') {
        sendPlainTextMessage(
            $replyContext['user_id'],
            $replyContext['access_token'],
            $message
        );
        return null;
    }

    if ($replyContext['channel'] === 'instagram_dm') {
        sendInstagramPrivateReply(
            $replyContext['user_id'],
            $message
        );
        return null;
    }

    return sendCommentReplyWithId($replyContext['comment_id'], $message);
}


// ============================================================
//  PARSERS
// ============================================================

function parseAutoCartComment(string $text): ?array
{
    if (!preg_match('/^\s*(ref(?:er[eê]n[cç][ei])?)[.\-:\s]*([A-Za-z0-9\-]+)/i', $text, $mRef)) {
        return null;
    }
    $ref = trim($mRef[2]);

    $text = preg_replace('/^\s*(ref(?:er[eê]n[cç][ei])?)[.\-:\s]*[A-Za-z0-9\-]+/i', '', $text);

    $qty = 1;

    if (preg_match('/\b(?:quantidade|qtde|quant|qty|x)[:\-\s]*([0-9]+)/i', $text, $mQty)) {
        $qty = (int)$mQty[1];
        $text = preg_replace('/\b(?:quantidade|qtde|quant|qty|x)[:\-\s]*[0-9]+/i', '', $text);
    } elseif (preg_match('/\b([0-9]+)\b/', $text, $mNum)) {
        $qty = (int)$mNum[1];
        $text = preg_replace('/\b[0-9]+\b/', '', $text, 1);
    }

    $parts = preg_split('/[,\s]+/', trim($text), -1, PREG_SPLIT_NO_EMPTY);
    $attrs = [];
    foreach ($parts as $p) {
        $p = preg_replace('/^(?:color|cor|tamanho|size)[:\-\s]*/i', '', $p);
        if ($p !== '') {
            $attrs[] = mb_strtolower($p);
        }
    }

    return [
        'ref'        => $ref,
        'qty'        => $qty,
        'attributes' => $attrs,
    ];
}


function parseCancelComment(string $text): ?array
{
    if (!preg_match('/ref[:\-\s]*([A-Za-z0-9\-]+)/i', $text, $mRef)) {
        return null;
    }
    $ref = trim($mRef[1]);

    $posRef = stripos($text, $mRef[0]);
    $text = substr($text, $posRef + strlen($mRef[0]));

    $parts = preg_split('/[,\s]+/', trim($text), -1, PREG_SPLIT_NO_EMPTY);
    $attrs = [];
    foreach ($parts as $p) {
        $p = preg_replace('/^(?:color|cor|tamanho|size)[:\-\s]*/i', '', $p);
        if ($p !== '') {
            $attrs[] = mb_strtolower($p);
        }
    }

    return [
        'ref'        => $ref,
        'attributes' => $attrs
    ];
}


function parseRefAnywhere(string $text): ?string
{
    if (preg_match('/\bref[:\-\s]*([A-Za-z0-9\-]+)/i', $text, $m)) {
        return trim($m[1]);
    }
    return null;
}


// ============================================================
//  BÚSQUEDA DE PRODUCTOS Y VARIACIONES
// ============================================================

function findVariation($prod, array $attrs, $woo): ?object
{
    if ($prod->type !== 'variable') {
        return null;
    }

    $variationAxes = array_filter($prod->attributes, function ($a) {
        return !empty($a->variation);
    });
    $numAxes = count($variationAxes);

    $attrs = array_map(function ($a) {
        return preg_replace('/\s+/', ' ', mb_strtolower(trim($a)));
    }, $attrs);

    if (count($attrs) !== $numAxes) {
        if (count($attrs) > $numAxes) {
            $combinations = generarCombinacionesAtributos($attrs, $numAxes);
            foreach ($combinations as $combo) {
                $v = findVariation($prod, $combo, $woo);
                if ($v) return $v;
            }
        }
        return null;
    }

    $vars = $woo->get("products/{$prod->id}/variations", ['per_page' => 100]);

    foreach ($vars as $v) {
        $opts = array_map(function ($attr) {
            return preg_replace('/\s+/', ' ', mb_strtolower(trim($attr->option)));
        }, $v->attributes);

        $match = true;
        foreach ($attrs as $attr) {
            if (!in_array($attr, $opts, true)) {
                $match = false;
                break;
            }
        }

        if ($match) {
            return $v;
        }
    }

    return null;
}


function findProductByRef(string $ref, $woo): ?object
{
    $res = $woo->get('products', [
        'sku'      => $ref,
        'status'   => 'publish',
        'per_page' => 1
    ]);
    if (!empty($res)) {
        return $res[0];
    }

    $res2 = $woo->get('products', [
        'search'   => $ref,
        'status'   => 'publish',
        'per_page' => 1
    ]);
    if (!empty($res2)) {
        return $res2[0];
    }

    return null;
}


// ============================================================
//  COMBINACIONES DE ATRIBUTOS
// ============================================================

function generarCombinacionesAtributos(array $attrs, int $esperado): array
{
    return combinarAtributosRecursivo($attrs, $esperado);
}

function combinarAtributosRecursivo(array $palabras, int $grupos, int $inicio = 0, array $actual = []): array
{
    $resultados = [];

    if ($grupos === 1) {
        $resto = array_slice($palabras, $inicio);
        $actual[] = implode(' ', $resto);
        return [$actual];
    }

    for ($i = $inicio + 1; $i <= count($palabras) - $grupos + 1; $i++) {
        $segmento = implode(' ', array_slice($palabras, $inicio, $i - $inicio));
        $siguientes = combinarAtributosRecursivo($palabras, $grupos - 1, $i, array_merge($actual, [$segmento]));
        foreach ($siguientes as $combo) {
            $resultados[] = $combo;
        }
    }

    return $resultados;
}


// ============================================================
//  ENVÍO DE RESPUESTAS A COMENTARIOS
// ============================================================

function sendCommentReplyWithId($fbcommentId, $message)
{
    $accessTokenManager = new FacebookTokenManager();
    $accessToken = $accessTokenManager->getAccessToken();

    $url = "https://graph.facebook.com/v20.0/{$fbcommentId}/comments?access_token={$accessToken}";

    $messageData = ['message' => $message];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($messageData));

    $result = curl_exec($ch);
    $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $response = json_decode($result, true);
    if ($httpStatus !== 200 || isset($response['error'])) {
        bot_log("[sendCommentReply] Error HTTP {$httpStatus}: " . $result);
        return false;
    }
    return $response['id'];
}


// ============================================================
//  PROCESO PRINCIPAL: AUTO-ADD
// ============================================================

function processAutoAdd(
    PDO    $conn,
    $liveId,
    $fbCommentId,
    $text,
    $userId,
    $woo,
    $httpApi,
    array  $replyContext = null,
    string $source = 'comment'
) {
    if ($replyContext === null) {
        $replyContext = [
            'channel'    => 'comment',
            'comment_id' => $fbCommentId,
        ];
    }

    // OBTENER ID INTERNO
    $internalCommentId = null;

    if ($source === 'messenger' || $source === 'instagram_dm') {
        $stmt = $conn->prepare("SELECT id FROM messenger_messages WHERE fb_message_id = :mid LIMIT 1");
        $stmt->execute([':mid' => $fbCommentId]);
        $internalCommentId = $stmt->fetchColumn();

        if (!$internalCommentId) {
            $stmt2 = $conn->prepare("
                SELECT m.id FROM messenger_messages m
                JOIN messenger_conversations c ON m.conversation_id = c.id
                WHERE c.user_id = :user_id AND m.is_from_page = 0
                ORDER BY m.created_at DESC LIMIT 1
            ");
            $stmt2->execute([':user_id' => $userId]);
            $internalCommentId = $stmt2->fetchColumn();
        }
    } else {
        $stmt = $conn->prepare("
            SELECT id_comment FROM live_comments WHERE fbcomment_id = :fb
            UNION
            SELECT id_comment FROM post_comments WHERE fbcomment_id = :fb
            LIMIT 1
        ");
        $stmt->execute([':fb' => $fbCommentId]);
        $internalCommentId = $stmt->fetchColumn();
    }

    if (!$internalCommentId) {
        bot_log("[processAutoAdd] Error: no se encontró id interno para id={$fbCommentId}, source={$source}");
        return;
    }

// Parsear texto
$data = parseAutoCartComment($text);
if (!$data) {
    if (preg_match('/^\s*([A-Za-z0-9\-]{2,})/i', $text, $mFallback)) {
        $posibleRef = trim($mFallback[1]);

        // Solo buscar por SKU exacto, NO por search
        $res = $woo->get('products', [
            'sku'      => $posibleRef,
            'status'   => 'publish',
            'per_page' => 1
        ]);

        if (!empty($res)) {
            botReply($replyContext, botTemplate('missing_ref', ['ref' => $posibleRef]));
        }
    }
    return;
}

    // Buscar producto
    $prod = findProductByRef($data['ref'], $woo);
    if (!$prod) {
        botReply($replyContext, botTemplate('not_found', ['ref' => $data['ref']]));
        return;
    }

    // Variación
    $variation = null;
    if ($prod->type === 'variable') {
        $variation = findVariation($prod, $data['attributes'], $woo);
        if (!$variation) {
            $axes = [];
            foreach ($prod->attributes as $attr) {
                if (!empty($attr->variation)) {
                    $axes[] = $attr->name;
                }
            }
            $need = implode(' e ', $axes);
            botReply($replyContext, botTemplate('need_attributes', ['product' => $prod->name, 'need' => $need]));
            return;
        }
    }

    // Stock, productId, sku, precio
    $stockQty   = $variation ? $variation->stock_quantity : $prod->stock_quantity;
    $productId  = $variation ? $variation->id             : $prod->id;
    $sku        = $prod->sku;
    $unitPrice  = $variation ? $variation->price          : $prod->price;

    $variationLabel = '';
    if (!empty($variation) && !empty($variation->attributes)) {
        $opts = array_map(function ($a) {
            return ucfirst(trim($a->option));
        }, $variation->attributes);
        $variationLabel = ' (' . implode(', ', $opts) . ')';
    }

    // DETECCIÓN DE DUPLICADOS
    $stmtCart = $conn->prepare("
        SELECT id_cart FROM cart
        WHERE id_user = :userId AND live_id = :liveId
        ORDER BY creation_date DESC LIMIT 1
    ");
    $stmtCart->execute([':userId' => $userId, ':liveId' => $liveId]);
    $idCart = $stmtCart->fetchColumn();

    if ($idCart) {
        $stmtDup = $conn->prepare("
            SELECT quantity, status, added_at FROM cart_items
            WHERE id_cart = :idCart AND id_product = :productId
              AND (added_by = 'user-facebook' OR added_by = 'user-messenger')
            LIMIT 1
        ");
        $stmtDup->execute([':idCart' => $idCart, ':productId' => $productId]);
        $dup = $stmtDup->fetch(PDO::FETCH_ASSOC);

        if ($dup) {
            $addedTs     = strtotime($dup['added_at']);
            $fiveDaysAgo = time() - 5 * 24 * 60 * 60;

            if ($dup['status'] !== 'paid' && $addedTs >= $fiveDaysAgo) {
                $existingQty  = (int)$dup['quantity'];
                $requestedQty = (int)$data['qty'];
                $totalQty     = $existingQty + $requestedQty;

                $variationLabelDup = '';
                if (!empty($variation)) {
                    $opts = array_map(function ($a) { return $a->option; }, $variation->attributes);
                    $variationLabelDup = ' (' . implode(', ', $opts) . ')';
                }
                $nameProduct = $prod->name . $variationLabelDup;

                // MESSENGER/INSTAGRAM DM: solo informa
                if ($source === 'messenger' || $source === 'instagram_dm') {
                    botReply($replyContext, botTemplate('already_in_cart', ['product' => $nameProduct, 'qty' => $existingQty, 'sku' => $sku]));
                    return;
                }

                // COMENTARIO: pedir confirmación
                $promptId = botReply($replyContext, botTemplate('confirm_duplicate', ['reqQty' => $requestedQty, 'totalQty' => $totalQty]));
                if (!$promptId) {
                    bot_log("[processAutoAdd] Error: no se pudo enviar prompt de confirmación");
                    return;
                }

                $stmtIns = $conn->prepare("
                    INSERT INTO pending_confirmations
                      (user_id, live_id, product_id, sku, unit_price, name_product,
                       internal_comment_id, prompt_comment_id, original_fbcomment_id,
                       existing_qty, requested_qty)
                    VALUES
                      (:userId, :liveId, :productId, :sku, :unitPrice, :nameProduct,
                       :intComment, :promptId, :origFb, :existQty, :reqQty)
                ");
                $stmtIns->execute([
                    ':userId'      => $userId,
                    ':liveId'      => $liveId,
                    ':productId'   => $productId,
                    ':sku'         => $sku,
                    ':unitPrice'   => $unitPrice,
                    ':nameProduct' => $nameProduct,
                    ':intComment'  => $internalCommentId,
                    ':promptId'    => $promptId,
                    ':origFb'      => $fbCommentId,
                    ':existQty'    => $existingQty,
                    ':reqQty'      => $requestedQty,
                ]);
                return;
            }
        }
    }

    // Stock reservado externo
    try {
        $resRes = $httpApi->get('/api/reserved-stock', [
            'query' => ['product_id' => $productId, 'live_id' => $liveId, 't' => time()]
        ]);
        $resBody       = json_decode((string)$resRes->getBody(), true);
        $reservedStock = isset($resBody['reservedStock']) ? (int)$resBody['reservedStock'] : 0;
    } catch (\Exception $e) {
        bot_log("[processAutoAdd] Error reserved-stock: " . $e->getMessage());
        $reservedStock = 0;
    }

    $availableStock = max(0, $stockQty - $reservedStock);

    // Sin stock
    if ($availableStock < $data['qty']) {
        if ($source === 'messenger' || $source === 'instagram_dm') {
            botReply($replyContext, botTemplate('out_of_stock', ['product' => $prod->name . $variationLabel, 'ref' => $data['ref']]));
        }

        try {
            $httpApi->post('/api/send-out-of-stock-message', [
                'json' => [
                    'user_id'      => $userId,
                    'product_ref'  => $data['ref'],
                    'live_id'      => $liveId,
                    'id_comment'   => (int)$internalCommentId,
                    'silent'       => true,
                    'id_product'   => $productId,
                    'quantity'     => $data['qty'],
                    'unit_price'   => (string)$unitPrice,
                    'name_product' => $prod->name . $variationLabel,
                    'sku'          => $sku,
                ]
            ]);
        } catch (\Exception $e) {
            bot_log("[processAutoAdd] Error OOS endpoint: " . $e->getMessage());
        }
        return;
    }

    // Add-to-cart
    $payload = [
        'seatNumber'  => null,
        'live_id'     => $liveId,
        'user_id'     => $userId,
        'id_comment'  => (int)$internalCommentId,
        'products'    => [[
            'sku'          => $sku,
            'product_id'   => (string)$productId,
            'quantity'     => $data['qty'],
            'unit_price'   => (string)$unitPrice,
            'name_product' => $prod->name . $variationLabel,
        ]]
    ];

    try {
        $res  = $httpApi->post('/api/add-to-cart', ['json' => $payload]);
        $body = json_decode((string)$res->getBody(), true);
        if (!empty($body['success'])) {

            if ($source === 'comment') {
                $checkStmt = $conn->prepare("
                    SELECT 'live' as tbl FROM live_comments WHERE fbcomment_id = :fb
                    UNION
                    SELECT 'post' as tbl FROM post_comments WHERE fbcomment_id = :fb
                    LIMIT 1
                ");
                $checkStmt->execute([':fb' => $fbCommentId]);
                $result = $checkStmt->fetch();

                if ($result) {
                    $table = $result['tbl'] === 'live' ? 'live_comments' : 'post_comments';
                    $conn->prepare("UPDATE {$table} SET addedToCart = 1 WHERE fbcomment_id = :fb")
                        ->execute([':fb' => $fbCommentId]);
                }
            }

            $addedBy = ($source === 'messenger' || $source === 'instagram_dm') ? 'user-messenger' : 'user-facebook';
            $conn->prepare("UPDATE cart_items SET added_by = :added_by, added_at = NOW() WHERE id_comment = :id_comment")
                ->execute([':added_by' => $addedBy, ':id_comment' => $internalCommentId]);

            if ($source === 'messenger' || $source === 'instagram_dm') {
                botReply($replyContext, botTemplate('added_to_cart', ['product' => $prod->name . $variationLabel, 'qty' => $data['qty']]));
            }
        }
    } catch (\Exception $e) {
        bot_log("[processAutoAdd] Error add-to-cart: " . $e->getMessage());
    }
}


// ============================================================
//  PROCESO: CANCELACIÓN
// ============================================================

function processCancelRequest(
    PDO    $conn,
    string $commentText,
    string $userId,
    string $liveId,
    string $commentId,
    $woo,
    array  $replyContext = null
): bool {
    if ($replyContext === null) {
        $replyContext = ['channel' => 'comment', 'comment_id' => $commentId];
    }

    if (stripos($commentText, 'cancelar') === false) {
        return false;
    }

    $dataCancel = parseCancelComment($commentText);
    if (!$dataCancel || empty($dataCancel['ref'])) {
        return true;
    }

    $refCancel = $dataCancel['ref'];
    $attrs = $dataCancel['attributes'];

    $prod = findProductByRef($refCancel, $woo);
    if (!$prod) {
        botReply($replyContext, botTemplate('cancel_not_found_product', ['ref' => $refCancel]));
        return true;
    }

    $productId = $prod->id;
    if ($prod->type === 'variable') {
        $variation = findVariation($prod, $attrs, $woo);
        if (!$variation) {
            $variationAxes = array_filter($prod->attributes, function ($a) {
                return !empty($a->variation);
            });
            $axes = array_map(function ($a) { return $a->name; }, $variationAxes);
            $need = implode(' e ', $axes);
            botReply($replyContext, botTemplate('cancel_need_attributes', ['product' => $prod->name, 'need' => $need]));
            return true;
        }
        $productId = $variation->id;
    }

    $stmtCart = $conn->prepare("SELECT id_cart FROM cart WHERE id_user = :userId ORDER BY creation_date DESC LIMIT 1");
    $stmtCart->execute([':userId' => $userId]);
    $idCart = $stmtCart->fetchColumn();
    if (!$idCart) {
        botReply($replyContext, botTemplate('cancel_no_cart'));
        return true;
    }

    $stmt = $conn->prepare("
        SELECT id_cart_item, name_product FROM cart_items
        WHERE id_cart = :idCart AND id_product = :productId
          AND (added_by = 'user-facebook' OR added_by = 'user-messenger')
          AND (status IS NULL OR status = 'unpaid')
        ORDER BY added_at DESC LIMIT 1
    ");
    $stmt->execute([':idCart' => $idCart, ':productId' => $productId]);
    $item = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$item) {
        botReply($replyContext, botTemplate('cancel_not_in_cart'));
        return true;
    }

    $cartItemId = $item['id_cart_item'];
    $itemName   = $item['name_product'];

    $conn->prepare("DELETE FROM cart_items WHERE id_cart_item = :id")->execute([':id' => $cartItemId]);

    sendNotification($userId, "Produto removido do seu carrinho", $itemName);

    $conn->prepare("
        INSERT INTO notifications (user_id, title, subtitle, date, type, status)
        VALUES (:user_id, :title, :subtitle, NOW(), 'remove-from-cart', 'unread')
    ")->execute([
        ':user_id'  => $userId,
        ':title'    => "Produto removido do seu carrinho",
        ':subtitle' => $itemName,
    ]);

    $stmt = $conn->prepare("SELECT COUNT(*) FROM cart_items WHERE id_cart = :idCart");
    $stmt->execute([':idCart' => $idCart]);
    $remaining = (int)$stmt->fetchColumn();

    if ($remaining === 0) {
        $conn->prepare("DELETE FROM cart WHERE id_cart = :id")->execute([':id' => $idCart]);
        $reply = "\"{$itemName}\" cancelado e seu carrinho ficou vazio.";
    } else {
        $reply = "\"{$itemName}\" cancelado. Ainda restam {$remaining} artigos no seu carrinho.";
    }

    botReply($replyContext, $reply);
    return true;
}


// ============================================================
//  PROCESO: LISTAR CARRITO
// ============================================================

function processListCartRequest(
    PDO    $conn,
    string $commentText,
    string $userId,
    string $liveId,
    string $commentId,
    array  $replyContext = null
): bool {
    if ($replyContext === null) {
        $replyContext = ['channel' => 'comment', 'comment_id' => $commentId];
    }

    $patterns = [
        '/bot.*\bquantos?\s+(artigos|itens)\s+(tenho|há)\b/i',
        '/bot.*\bque\s+tem.*\bno\s+meu\s+carrinho\b/i',
        '/bot.*\bmeu\s+carrinho\b.*\bquantos?\b/i',
        '/\bver\s+carrinho\b/i',
        '/\bmeu\s+carrinho\b/i',
        '/\blistar\s+carrinho\b/i',
        '/\bquantos?\s+(artigos|itens)\s+(tenho|há)\b/i',
        '/\bque\s+tem.*\bno\s+meu\s+carrinho\b/i',
    ];
    $matched = false;
    foreach ($patterns as $pat) {
        if (preg_match($pat, $commentText)) {
            $matched = true;
            break;
        }
    }
    if (!$matched) {
        return false;
    }

    $stmt = $conn->prepare("
        SELECT id_cart FROM cart WHERE id_user = :userId ORDER BY creation_date DESC LIMIT 1
    ");
    $stmt->execute([':userId' => $userId]);
    $idCart = $stmt->fetchColumn();
    if (!$idCart) {
        botReply($replyContext, botTemplate('cart_empty'));
        return true;
    }

    $stmt = $conn->prepare("
        SELECT name_product, quantity FROM cart_items
        WHERE id_cart = :idCart AND (status IS NULL OR status = 'unpaid')
    ");
    $stmt->execute([':idCart' => $idCart]);
    $items = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (empty($items)) {
        botReply($replyContext, botTemplate('cart_empty'));
        return true;
    }

    $lines = [];
    foreach ($items as $it) {
        $lines[] = "- {$it['name_product']}: {$it['quantity']} unidades";
    }
    $reply = "Tens esses artigos no seu carrinho:\n" . implode("\n", $lines);

    botReply($replyContext, $reply);
    return true;
}


// ============================================================
//  PROCESO: CONFIRMACIÓN (solo comentarios)
// ============================================================

function processConfirmRequest(
    $conn,
    $parentId,
    $normalizedText,
    $commentId,
    $liveId,
    $wooClient,
    $httpApi,
    array $replyContext = null
): bool {
    if ($replyContext === null) {
        $replyContext = ['channel' => 'comment', 'comment_id' => $commentId];
    }

    if (!preg_match('/(?:^|\s)confirmar$/', $normalizedText)) {
        return false;
    }

    $stmt = $conn->prepare("
        SELECT * FROM pending_confirmations
        WHERE status = 'pending'
          AND (prompt_comment_id = :pid OR original_fbcomment_id = :pid)
        LIMIT 1
    ");
    $stmt->execute([':pid' => $parentId]);
    $pend = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$pend) {
        botReply($replyContext, botTemplate('no_pending_confirm'));
        return true;
    }

    $existingQty  = (int)$pend['existing_qty'];
    $requestedQty = (int)$pend['requested_qty'];
    $totalQty     = $existingQty + $requestedQty;

    try {
        $prodInfo = $wooClient->get("products/{$pend['product_id']}");
        $stockQty = isset($prodInfo->stock_quantity) ? (int)$prodInfo->stock_quantity : 0;
    } catch (\Exception $e) {
        bot_log("[processConfirm] Error stock base: " . $e->getMessage());
        $stockQty = 0;
    }

    try {
        $res = $httpApi->get('/api/reserved-stock', [
            'query' => ['product_id' => $pend['product_id'], 'live_id' => $liveId, 't' => time()]
        ]);
        $body = json_decode((string)$res->getBody(), true);
        $reservedStock = isset($body['reservedStock']) ? (int)$body['reservedStock'] : 0;
    } catch (\Exception $e) {
        bot_log("[processConfirm] Error reserved-stock: " . $e->getMessage());
        $reservedStock = 0;
    }

    $availableStock = max(0, $stockQty - $reservedStock);
    if ($availableStock < $requestedQty) {
        botReply($replyContext, botTemplate('not_enough_stock', ['stock' => $availableStock]));
        return true;
    }

    $stmt2 = $conn->prepare("
        SELECT id_cart_item, name_product FROM cart_items
        WHERE id_product = :productId
          AND (added_by = 'user-facebook' OR added_by = 'user-messenger')
          AND (status IS NULL OR status = 'unpaid')
        ORDER BY added_at DESC LIMIT 1
    ");
    $stmt2->execute([':productId' => $pend['product_id']]);
    $item = $stmt2->fetch(PDO::FETCH_ASSOC);
    if (!$item) {
        botReply($replyContext, botTemplate('update_not_found'));
        return true;
    }

    $cartItemId = $item['id_cart_item'];
    $itemName   = $item['name_product'];

    $conn->prepare("UPDATE cart_items SET quantity = :totalQty WHERE id_cart_item = :cartItemId")
        ->execute([':totalQty' => $totalQty, ':cartItemId' => $cartItemId]);

    $conn->prepare("UPDATE pending_confirmations SET status = 'confirmed' WHERE id = :id")
        ->execute([':id' => $pend['id']]);

    botReply($replyContext, botTemplate('confirmed_qty', ['totalQty' => $totalQty]));
    sendNotification($pend['user_id'], "Adicionou mais {$requestedQty} unidade(s) do artigo", $itemName);

    return true;
}