<?php
// publicarml_wizard.php — Wizard web para publicar en ML paso a paso

require __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/config/db.php';  // Debe definir $conn = new mysqli(...)
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

const SITE_ID           = 'MCO';
const PREDICT_LIMIT     = 8;
const CATEGORY_FALLBACK = 'MCO12345';
const DEFAULT_BRAND     = 'Genérica';  // o 'Compranet' si prefieres

$http = new Client([
    'base_uri' => 'https://api.mercadolibre.com',
    'timeout'  => 30,
]);

function getCredentials(mysqli $conn): array
{
    $res = $conn->query("
      SELECT user_id, access_token, refresh_token, expires_in, updated_at
        FROM tb_marketplace_tokens
       WHERE idMP=1
       ORDER BY updated_at DESC
       LIMIT 1
    ");
    if (!$row = $res->fetch_assoc()) {
        die("<p class='error'>ERROR: Ejecuta authorize.php primero.</p>");
    }
    return [
        'user_id'       => $row['user_id'],
        'access_token'  => $row['access_token'],
        'refresh_token' => $row['refresh_token'],
        'expires_in'    => $row['expires_in'],
        'updated_at'    => $row['updated_at'],
    ];
}

function refreshTokenIfNeeded(Client $http, array &$creds, mysqli $conn)
{
    $expTs = strtotime($creds['updated_at']) + $creds['expires_in'];
    if (time() < $expTs - 60) return;
    $r = $http->post('/oauth/token', [
        'form_params' => [
            'grant_type'    => 'refresh_token',
            'client_id'     => '3658695067033012',
            'client_secret' => 'GZBg63xJNM9Eeb2cOhF9JwsOEv6vTxo7',
            'refresh_token' => $creds['refresh_token']
        ],
        'headers' => ['Accept' => 'application/json']
    ]);
    $d = json_decode((string)$r->getBody(), true);
    foreach (['access_token', 'refresh_token', 'expires_in'] as $k) {
        $creds[$k] = $d[$k];
    }
    $u = $conn->prepare("
      UPDATE tb_marketplace_tokens
         SET access_token=?, refresh_token=?, expires_in=?, updated_at=NOW()
       WHERE user_id=?
    ");
    $u->bind_param(
        'ssis',
        $creds['access_token'],
        $creds['refresh_token'],
        $creds['expires_in'],
        $creds['user_id']
    );
    $u->execute();
    $u->close();
}

function updateWithRetry(Client $http, string $m, string $e, string $t, array $p = [], int $r = 3)
{
    $a = 0;
    while (true) {
        try {
            usleep(100000);
            $opts = [
                'headers' => [
                    'Authorization' => "Bearer {$t}",
                    'Content-Type'  => 'application/json'
                ]
            ];
            if ($m !== 'GET') $opts['json'] = $p;
            $resp = match ($m) {
                'GET'  => $http->get($e, $opts),
                'POST' => $http->post($e, $opts),
                default => $http->put($e, $opts)
            };
            return json_decode((string)$resp->getBody(), true);
        } catch (RequestException $x) {
            $code = $x->getResponse()?->getStatusCode() ?: 0;
            if ($code === 429 && $a++ < $r) {
                sleep((int)$x->getResponse()->getHeaderLine('Retry-After') ?: 5);
                continue;
            }
            throw $x;
        }
    }
}

function predictCategories(Client $http, string $token, string $q): array
{
    try {
        $r = $http->get("/sites/" . SITE_ID . "/domain_discovery/search", [
            'headers' => ['Authorization' => "Bearer {$token}", 'Accept' => 'application/json'],
            'query'  => ['limit' => PREDICT_LIMIT, 'q' => $q]
        ]);
        return json_decode((string)$r->getBody(), true) ?: [];
    } catch (RequestException) {
        return [];
    }
}

function fetchCategoryPath(Client $http, string $catId): string
{
    try {
        $r = $http->get("/categories/{$catId}", ['headers' => ['Accept' => 'application/json']]);
        $d = json_decode((string)$r->getBody(), true);
        $names = array_column($d['path_from_root'], 'name');
        return implode(' › ', $names);
    } catch (RequestException) {
        return $catId;
    }
}

function uploadPicture(Client $http, string $token, string $url): ?string
{
    try {
        $r = $http->post('/pictures', [
            'headers' => ['Authorization' => "Bearer {$token}", 'Content-Type' => 'application/json'],
            'json'   => ['source' => $url]
        ]);
        $d = json_decode((string)$r->getBody(), true);
        // ——>> LOG: respuesta completa
        file_put_contents(__DIR__ . '/ml_pictures.log', date('c') . " | URL: {$url}\n" . print_r($d, true) . "\n", FILE_APPEND);
        return $d['id'] ?? null;
    } catch (RequestException $x) {
        file_put_contents(__DIR__ . '/ml_pictures.log', date('c') . " | ERROR cargando {$url}: " . $x->getMessage() . "\n", FILE_APPEND);
        return null;
    }
}


function e(?string $s): string
{
    // si viene null, lo convertimos en cadena vacía
    return htmlspecialchars((string)$s, ENT_QUOTES);
}

?>
<!doctype html>
<html lang="es">

<head>
    <meta charset="utf-8">
    <title>Publicar ML Wizard</title>
    <link rel="stylesheet" href="/css/compranet.css">
    <style>
        .wizard {
            max-width: 900px;
            margin: 2em auto;
            background: #fff;
            padding: 1em;
            border: 1px solid #ddd
        }

        .step {
            margin-bottom: 2em
        }

        .btn {
            padding: .5em 1em;
            background: #007bff;
            color: white;
            border: none;
            cursor: pointer
        }

        .btn:hover {
            background: #0056b3
        }

        .form-control {
            width: 100%;
            padding: .5em;
            margin: .2em 0 1em
        }

        .variations-row {
            display: flex;
            gap: 1em;
            flex-wrap: wrap
        }

        .variations-row fieldset {
            flex: 1;
            min-width: 200px
        }

        .error {
            color: #c00
        }

        .success {
            color: #090
        }
    </style>
</head>

<body>
    <div class="wizard">
        <h1>Publicar en MercadoLibre</h1>

        <?php
        // — Preload credenciales y token
        $creds = getCredentials($conn);
        refreshTokenIfNeeded($http, $creds, $conn);
        $token = $creds['access_token'];

        $stage      = $_REQUEST['stage']      ?? 'list';
        $product_id = (int)($_REQUEST['product_id'] ?? 0);

        // — 1) LISTAR productos pendientes —
        if ($stage === 'list') {
            echo '<div class="step"><h2>1) Productos pendientes</h2><ul>';
            $res = $conn->query("
        SELECT p.id, CONCAT(p.tituloPublicacion,' - ',p.skuMP) AS  tituloPublicacion,pr.descripcion AS descripcion,
         pr.txtMedidas, pr.txtMaterial, p.idProducto 
        FROM tb_marketplace_productos p
        JOIN tb_productos pr ON p.idProducto=pr.id
       WHERE p.idMarketplace=1 AND p.activo=1 AND p.refMP IS NULL
    ");
            while ($r = $res->fetch_assoc()) {
                printf(
                    "<li>
           <strong>%s</strong><br>
           <small>%s</small><br>
           Medidas: %s | Material: %s<br>
           <a class='btn' href='?stage=select_category&product_id=%d'>Publicar »</a>
         </li><hr>",
                    e($r['tituloPublicacion']),
                    e($r['descripcion']),
                    e($r['txtMedidas']),
                    e($r['txtMaterial']),
                    $r['id']
                );
            }
            echo '</ul></div></div></body></html>';
            exit;
        }

        // — 2) SELECCIONAR categoría —
        if ($stage === 'select_category') {
            // cargo datos del producto
            $row = $conn->query("
      SELECT p.tituloPublicacion, pr.descripcion AS descripcion, pr.txtMedidas, pr.txtMaterial
        FROM tb_marketplace_productos p
        JOIN tb_productos pr ON p.idProducto=pr.id
       WHERE p.id={$product_id}
    ")->fetch_assoc();
            $title = $row['tituloPublicacion'];
            $desc  = $row['descripcion'];
            $med   = $row['txtMedidas'];
            $mat   = $row['txtMaterial'];

            // buscar o usar título como query
            $search = $_REQUEST['search_query'] ?? $title;
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                $cat = $_POST['category_id'];
                header("Location:?stage=fill_attributes&product_id={$product_id}&category_id={$cat}");
                exit;
            }
            $preds = predictCategories($http, $token, $search);

            // filtro solo categorías que acepten variaciones
            // 2) Generar listado de categorías que admitan variaciones
            $candidates = [];

            foreach ($preds as $p) {
                // Traemos los atributos de la categoría (con token)
                $attrs = updateWithRetry(
                    $http,
                    'GET',
                    "/categories/{$p['category_id']}/attributes",
                    $token
                );

                // Buscamos si tiene algún atributo de variación
                $hasVariation = false;
                foreach ($attrs as $a) {
                    if (
                        (($a['hierarchy'] ?? '') === 'CHILD_PK')
                        || !empty($a['tags']['variation_attribute'])
                    ) {
                        $hasVariation = true;
                        break;
                    }
                }

                if ($hasVariation) {
                    // Obtenemos la ruta desde la raíz para mostrar el árbol
                    $path = fetchCategoryPath($http, $p['category_id']);

                    $candidates[] = [
                        'id'   => $p['category_id'],
                        'name' => e($path)
                    ];
                }
            }

            // Si no hay ninguna categoría con variaciones, usamos el fallback
            if (empty($candidates)) {
                $candidates[] = [
                    'id'   => CATEGORY_FALLBACK,
                    'name' => CATEGORY_FALLBACK . ' (fallback)'
                ];
            }


            echo '<div class="step"><h2>2) Selecciona categoría</h2>';
            echo "<p><strong>" . e($title) . "</strong><br>" . e($desc) . "<br>Medidas: " . e($med) . " | Material: " . e($mat) . "</p>";

            // formulario de búsqueda
            echo "<form method='get'>
            <input type='hidden' name='stage' value='select_category'>
            <input type='hidden' name='product_id' value='{$product_id}'>
            <input class='form-control' type='text' name='search_query' value='" . e($search) . "' placeholder='Buscar categoría...'>
            <button class='btn'>Buscar</button>
          </form>";

            // dropdown de candidatos
            echo "<form method='post'>
            <input type='hidden' name='product_id' value='{$product_id}'>
            <select class='form-control' name='category_id'>";
            foreach ($candidates as $c) {
                printf("<option value='%s'>%s</option>", e($c['id']), e($c['name']));
            }
            echo   "</select>
            <button class='btn'>Siguiente »</button>
          </form>
        </div></div></body></html>";
            exit;
        }

        // — 3) RELLENAR atributos y variaciones —
        if ($stage === 'fill_attributes') {
            $category_id = $_REQUEST['category_id'];

            // cargo datos del producto
            $prod = $conn->query("
      SELECT p.tituloPublicacion, pr.descripcion AS descripcion, pr.txtMedidas, pr.txtMaterial,
             p.precioPublicacion, p.stockPublicacion, p.skuMP
        FROM tb_marketplace_productos p
        JOIN tb_productos pr ON p.idProducto=pr.id
       WHERE p.id={$product_id}
    ")->fetch_assoc();

            // cargo variaciones (solo stock>0)
            $vars = [];
            $stmt = $conn->prepare("
      SELECT v.idVariante,v.skuMPVariante,v.precioPublicacion,v.stockPublicacion,
             v.colorTipoVariante, iv.linkImagen
        FROM tb_marketplace_variantes v
        JOIN tb_imagenes_variantes iv ON v.idVariante=iv.idVariante
       WHERE v.idMarketplaceProducto=? AND v.stockPublicacion>0
    ");
            $stmt->bind_param('i', $product_id);
            $stmt->execute();
            $stmt->bind_result($idVar, $vs, $vp, $vsx, $vc, $vi);

            while ($stmt->fetch()) {
                $vars[] = [
                    'id'    => $idVar,
                    'sku' => $vs,
                    'price' => $vp,
                    'stock' => $vsx,
                    'color' => $vc,
                    'img' => str_replace('J:/', 'https://sistema.compranet.com.co/', $vi)
                ];
            }
            $stmt->close();

            // obtengo spec UI de la categoría
            try {
                $tech = updateWithRetry($http, 'GET', "/categories/{$category_id}/technical_specs/input", $token, [], 1);
            } catch (RequestException $ex) {
                $tech = ['groups' => []];
            }

            if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                $qs = http_build_query([
                    'stage' => 'publish',
                    'product_id' => $product_id,
                    'category_id' => $category_id
                ]);
                header("Location:?{$qs}&" . http_build_query($_POST));
                exit;
            }

            // render
            echo '<div class="step"><h2>3) Completa atributos y variaciones</h2>';
            echo "<p><strong>" . e($prod['tituloPublicacion']) . "</strong><br>"
                . e($prod['descripcion']) . "<br>"
                . "Medidas: " . e($prod['txtMedidas']) . " | Material: " . e($prod['txtMaterial']) . "</p>";

            echo "<form method='post'>
            <input type='hidden' name='product_id'   value='{$product_id}'>
            <input type='hidden' name='category_id'  value='" . e($category_id) . "'>";

            // recorro grupos y componentes
            foreach ($tech['groups'] as $group) {
                echo "<h3>" . e($group['label']) . "</h3>";
                foreach ($group['components'] as $comp) {
                    $ui = $comp['ui_config'] ?? [];
                    foreach ($comp['attributes'] as $attr) {
                        // salto hidden
                        // salto atributos ocultos, de solo lectura o de variación
                        // salto hidden, read_only o variation_attribute (tanto si vienen como keys o como valores)
                        $tags = $attr['tags'] ?? [];
                        foreach (['hidden', 'read_only', 'variation_attribute'] as $t) {
                            if ((isset($tags[$t]) && $tags[$t]) || in_array($t, $tags, true)) {
                                continue 2;  // salta este atributo
                            }
                        }
                        // además salto cualquier PACKAGE_*
                        if (strpos($attr['id'], 'PACKAGE_') === 0) {
                            continue;
                        }


                        // --- Definir siempre el id y abrir el div/label ---
                        $id   = e($attr['id']);
                        $name = e($attr['name']);
                        echo "<div class='form-group'><label>{$name} ({$id}):</label>";

                        // override MODEL
                        if ($attr['id'] === 'MODEL') {
                            echo "<input class='form-control' name='attr_MODEL' value='" . e($prod['skuMP']) . "' readonly>";
                            echo "</div>";  // cierro el div que abrí arriba
                            continue;
                        }

                        // override BRAND
                        if ($attr['id'] === 'BRAND') {
                            echo "<input class='form-control' name='attr_BRAND' value='" . e(DEFAULT_BRAND) . "' readonly>";
                            echo "</div>";
                            continue;
                        }

                        // valor fixed → auto-assign + readonly
                        if (!empty($attr['tags']['fixed']) && count($attr['values'] ?? []) === 1) {
                            $only = $attr['values'][0];
                            echo "<input class='form-control' readonly value='" . e($only['name']) . "'>";
                            echo "<input type='hidden' name='attr_{$id}' value='" . e($only['id']) . "'>";
                        }
                        // COMBO → select o datalist
                        elseif ($comp['component'] === 'COMBO') {
                            $vals = $attr['values'] ?? [];
                            if (!empty($ui['allow_filtering'])) {
                                // uso datalist
                                $listId = "lst_{$id}";
                                echo "<input list='{$listId}' name='attr_{$id}' class='form-control' placeholder='Filtrar o escribir'>";
                                echo "<datalist id='{$listId}'>";
                                foreach ($vals as $v) {
                                    printf("<option value='%s'>", e($v['name']));
                                }
                                echo "</datalist>";
                            } else {
                                // normal select
                                echo "<select class='form-control' name='attr_{$id}'>";
                                if (!$comp['required'] ?? false) {
                                    echo "<option value=''>— ninguno —</option>";
                                }
                                foreach ($vals as $v) {
                                    printf("<option value='%s'>%s</option>", e($v['id']), e($v['name']));
                                }
                                echo "</select>";
                            }
                        }
                        // TEXT_INPUT → input libre
                        elseif ($comp['component'] === 'TEXT_INPUT') {
                            $val = $ui['allow_custom_value'] ? '' : '';
                            echo "<input class='form-control' name='attr_{$id}' value='" . e($val) . "'>";
                        }
                        // NUMBER_UNIT, BOOLEAN, etc → campo texto libre (podrías especializarlo)
                        else {
                            echo "<input class='form-control' name='attr_{$id}'>";
                        }

                        echo "</div>";
                    }
                }
            }

            // variaciones
            echo "<h3>Variaciones</h3><div class='variations-row'>";
            // determinar varAttrId
            $varAttrId = 'COLOR';
            foreach ($tech['groups'] as $g) {
                foreach ($g['components'] as $c) {
                    foreach ($c['attributes'] as $a) {
                        if (!empty($a['tags']['variation_attribute'])) {
                            $varAttrId = $a['id'];
                            break 3;
                        }
                    }
                }
            }
            foreach ($vars as $i => $v) {
                echo "<fieldset><legend>SKU " . e($v['sku']) . "</legend>";
                printf(
                    "Precio:<input class='form-control' name='var_%d_price' value='%s'><br>",
                    $i,
                    e($v['price'])
                );
                printf(
                    "Stock: <input class='form-control' name='var_%d_stock' value='%s'><br>",
                    $i,
                    e($v['stock'])
                );

                // combinaciones
                // busco los valores del varAttrId
                $vals = [];
                foreach ($tech['groups'] as $g) {
                    foreach ($g['components'] as $c) {
                        foreach ($c['attributes'] as $a) {
                            if ($a['id'] === $varAttrId) {
                                $vals = $a['values'] ?? [];
                                break 3;
                            }
                        }
                    }
                }
                // Pon esto:
                echo "<div class='form-group'>";
                echo "<label>Color:</label>";
                // muestro el color actual en un input de solo lectura
                echo "<input 
        type='text' 
        class='form-control' 
        name='var_{$i}_combo' 
        value='" . e($v['color']) . "' 
        readonly
     >";
                // envío el mismo valor oculto para que llegue en el POST
                echo "<input 
        type='hidden' 
        name='var_{$i}_combo' 
        value='" . e($v['color']) . "'
     >";
                echo "</div>";

                echo "</fieldset>";

                echo "</fieldset>";
            }
            echo "</div>";

            echo "<button class='btn'>Publicar »</button>";
            echo "</form></div></div></body></html>";
            exit;
        }

        // — 4) PUBLICAR final —
        if ($stage === 'publish') {
            $category_id = $_REQUEST['category_id'];
            // recargo datos
            $row = $conn->query("
      SELECT p.tituloPublicacion, p.descripcionPublicacion AS descripcion, pr.txtMedidas, pr.txtMaterial,
             p.precioPublicacion, p.stockPublicacion, p.skuMP
        FROM tb_marketplace_productos p
        JOIN tb_productos pr ON p.idProducto=pr.id
       WHERE p.id={$product_id}
    ")->fetch_assoc();
            $title       = $row['tituloPublicacion'];
            $description = $row['descripcion'];
            $price       = $row['precioPublicacion'];
            $stock       = $row['stockPublicacion'];
            $sku_main    = $row['skuMP'];

            // variaciones
            $vars = [];
            $stmt = $conn->prepare("
      SELECT v.idVariante,v.skuMPVariante,v.precioPublicacion,v.stockPublicacion,iv.linkImagen
        FROM tb_marketplace_variantes v
        JOIN tb_imagenes_variantes iv ON v.idVariante=iv.idVariante
       WHERE v.idMarketplaceProducto=? AND v.stockPublicacion>0
    ");
            $stmt->bind_param('i', $product_id);
            $stmt->execute();
            $stmt->bind_result(
                $idVar,  // idVariante
                $vs,     // skuMPVariante
                $vp,     // precioPublicacion
                $vsx,    // stockPublicacion
                $vi      // linkImagen
            );

            while ($stmt->fetch()) {
                $vars[] = [
                    'id'    => $idVar,
                    'sku' => $vs,
                    'price' => $vp,
                    'stock' => $vsx,
                    'img' => str_replace('J:/', 'https://sistema.compranet.com.co/', $vi)
                ];
            }
            $stmt->close();
            // 1) Cargo y filtro los atributos permitidos
            $meta = updateWithRetry(
                $http,
                'GET',
                "/categories/{$category_id}/attributes",
                $token,
                [],
                1
            );
            $allowed = array_filter($meta, function ($a) {
                $tags = $a['tags'] ?? [];
                foreach (['hidden', 'read_only', 'variation_attribute'] as $t) {
                    if ((isset($tags[$t]) && $tags[$t]) || in_array($t, $tags, true)) {
                        return false;
                    }
                }
                // no permito PACKAGE_*
                if (strpos($a['id'], 'PACKAGE_') === 0) {
                    return false;
                }
                return true;
            });
            $allowedIds = array_column($allowed, 'id');

            // 2) Construyo topAttrs A PARTIR DE allowedIds
            $topAttrs = [];
            foreach ($_GET as $k => $v) {
                if (!str_starts_with($k, 'attr_') || $v === '') continue;
                $aid = substr($k, 5);
                if (!in_array($aid, $allowedIds, true)) continue;
                $topAttrs[] = is_numeric($v)
                    ? ['id' => $aid, 'value_id'   => $v]
                    : ['id' => $aid, 'value_name' => $v];
            }
            // 3) Salvavidas extra: elimino cualquier PACKAGE_*
            $topAttrs = array_values(array_filter(
                $topAttrs,
                fn($a) => strpos($a['id'], 'PACKAGE_') !== 0
            ));

            $allowedIds = array_column($allowed, 'id');
            // ya tienes $allowed (filtrado) justo arriba…
            $varAttrId = 'COLOR';
            foreach ($allowed as $a) {
                $tags = $a['tags'] ?? [];
                if (
                    (isset($tags['variation_attribute']) && $tags['variation_attribute'])
                    || in_array('variation_attribute', $tags, true)
                ) {
                    $varAttrId = $a['id'];
                    break;
                }
            }


            // build variations payload
            $varsPayload = [];
            foreach ($vars as $i => $v) {
                $vp = (float)($_GET["var_{$i}_price"] ?? $v['price']);
                $vs = (int)  ($_GET["var_{$i}_stock"] ?? $v['stock']);
                $vc = $_GET["var_{$i}_combo"] ?? '';
                $comb = $vc
                    ? [['id' => $varAttrId, 'value_name' => $vc]]
                    : [];
                $entry = [
                    'seller_custom_field'   => $v['sku'],
                    'price'                 => $vp,
                    'available_quantity'    => $vs,
                    'attribute_combinations' => $comb,
                    'attributes' => [
                        [
                            'id'         => 'SELLER_SKU',
                            'value_name' => $v['sku']
                        ]
                    ]
                ];
                if ($pic = uploadPicture($http, $token, $v['img'])) {
                    $entry['picture_ids'] = [$pic];
                } else {
                    file_put_contents(__DIR__ . '/ml_pictures.log', date('c') . " | NO se obtuvo ID para SKU {$v['sku']} URL {$v['img']}\n", FILE_APPEND);
                }
                $varsPayload[] = $entry;
            }

            // sale_terms fijos
            $sale_terms = [
                ['id' => 'WARRANTY_TYPE', 'value_id' => '2230280'],
                ['id' => 'WARRANTY_TIME', 'value_name' => '30 días'],
                ['id' => 'MANUFACTURING_TIME', 'value_name' => '3 días'],
            ];

            $topAttrs = array_values(array_filter($topAttrs, fn($a) => strpos($a['id'], 'PACKAGE_') !== 0));
            // payload final
            $payload = [
                'site_id' => SITE_ID,
                'title' => $title,
                'category_id' => $category_id,
                'price' => $price,
                'currency_id' => 'COP',
                'available_quantity' => $stock,
                'buying_mode' => 'buy_it_now',
                'listing_type_id' => 'gold_pro',
                'condition' => 'new',
                'seller_custom_field' => $sku_main,
                'accepts_mercadopago' => true,
                'shipping' => ['mode' => 'not_specified', 'local_pick_up' => false],
                'sale_terms' => $sale_terms,
                'pictures' => [],
                'attributes' => $topAttrs,
                'variations' => $varsPayload
            ];

            echo '<div class="step"><h2>4) Resultado de la publicación</h2>';
            try {
                $resp = updateWithRetry($http, 'POST', '/items', $token, $payload);
                $itemData = updateWithRetry($http, 'GET', "/items/{$resp['id']}", $token, [], 1);
                file_put_contents(
                    __DIR__ . '/ml_pictures.log',
                    date('c') . " | ITEM {$resp['id']} pictures:\n" . print_r($itemData['pictures'] ?? [], true) . "\n\n",
                    FILE_APPEND
                );

                if (!empty($resp['id'])) {
                    $ml = $resp['id'];
                    $u = $conn->prepare("
          UPDATE tb_marketplace_productos
             SET refMP=?, fechaSincronizacion=NOW()
           WHERE id=?
        ");

                    // 1.a) Subo la descripción en un llamado aparte
                    updateWithRetry(
                        $http,
                        'POST',
                        "/items/{$ml}/description",
                        $token,
                        ['plain_text' => $description]
                    );

                    // — Actualizar variantes con sus IDs en ML —
                    try {
                        $itemData = updateWithRetry($http, 'GET', "/items/{$ml}", $token, [], 1);
                        foreach ($itemData['variations'] ?? [] as $var) {
                            // $var['seller_custom_field'] es tu SKU local
                            $remoteVarId = $var['id'];
                            $localSku     = $var['seller_custom_field'];
                            $upVar = $conn->prepare("
        UPDATE tb_marketplace_variantes
           SET refMPVariante = ?
         WHERE skuMPVariante = ? AND idMarketplaceProducto = ?
      ");
                            $upVar->bind_param('ssi', $remoteVarId, $localSku, $product_id);
                            $upVar->execute();
                            $upVar->close();
                        }
                    } catch (RequestException $e) {
                        // opcionalmente loguear el error…
                    }

                    $u->bind_param('si', $ml, $product_id);
                    $u->execute();
                    $u->close();
                    echo "<p class='success'>✅ Publicado con ID {$ml}</p>";
                } else {
                    echo "<p class='error'>❌ No devolvió ID.</p>";
                }
            } catch (RequestException $x) {
                $err  = json_decode((string)$x->getResponse()->getBody(), true);
                $msgs = array_map(fn($c) => $c['message'] ?? $c['field'], $err['cause'] ?? []);
                echo "<p class='error'>❗ " . implode(', ', $msgs) . "</p>";
            }
            echo "<p><a class='btn' href='?stage=list'>← Empezar otro</a></p>";
            echo '</div></div></body></html>';
            exit;
        }

        // Etapa desconocida
        echo "<p class='error'>Etapa desconocida.</p></div></body></html>";
