<?php
session_start();
ob_start();   // <<--- aquí
require __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/config/db.php';  // Debe definir $conn = new mysqli(...)
require_once __DIR__ . '/../../includes/user_activity_log.php';
require_once __DIR__ . '/../../cotizaciones/api/_node.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

const SITE_ID           = 'MCO';
const PREDICT_LIMIT     = 8;
const CATEGORY_FALLBACK = 'MCO12345';
const DEFAULT_BRAND     = 'Genérica';

$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 [];
    }
}

/**
 * Ahora recibe también el token y devuelve siempre:
 *  - "Padre › Hijo › Nieto…" si existe path_from_root
 *  - o bien el campo 'name' de la categoría
 *  - o el catId como último recurso
 */
function fetchCategoryPath(Client $http, string $token, string $catId): string
{
    try {
        // incluimos la Authorization para no depender de CORS o de endpoints públicos
        $resp = $http->get("/categories/{$catId}", [
            'headers' => [
                'Authorization' => "Bearer {$token}",
                'Accept'        => 'application/json'
            ]
        ]);
        $d = json_decode((string)$resp->getBody(), true);

        // 1) intentamos la ruta completa
        $path = array_column($d['path_from_root'] ?? [], 'name');
        if (!empty($path)) {
            return implode(' › ', $path);
        }

        // 2) fallback al nombre simple
        if (!empty($d['name'])) {
            return $d['name'];
        }

        // 3) si algo falla, devolvemos el ID
        return $catId;
    } catch (RequestException $e) {
        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
{
    return htmlspecialchars((string)$s, ENT_QUOTES);
}

// ───────────────────── AJAX proxy a Node (MercadoLibre) ─────────────────────
if (isset($_GET['ajax'])) {
    header('Content-Type: application/json; charset=utf-8');

    $base = cpn_node_api_base();
    $token = $_SESSION['node_token'] ?? '';
    if (!is_string($token) || trim($token) === '') {
        http_response_code(401);
        echo json_encode(['ok' => false, 'error' => ['message' => 'Token de sesión Node no disponible. Inicie sesión de nuevo.']]);
        exit;
    }

    $ajax = (string)$_GET['ajax'];

    if ($ajax === 'ml_import_start') {
        $url = rtrim($base, '/') . '/api/integrations/mercadolibre/import?async=1';
        $resp = cpn_node_request('POST', $url, $token, []);

        if (!empty($resp['ok'])) {
            cpn_activity_log_event('marketplace', 'marketplace.mercadolibre_import_start', 'Inició importación MercadoLibre (async)', 'marketplace', 1, []);
        }

        echo json_encode($resp);
        exit;
    }

    if ($ajax === 'ml_import_progress') {
        $url = rtrim($base, '/') . '/api/integrations/mercadolibre/import/progress';
        $resp = cpn_node_request('GET', $url, $token, null);
        echo json_encode($resp);
        exit;
    }

    if ($ajax === 'ml_sync_start') {
        $url = rtrim($base, '/') . '/api/integrations/mercadolibre/sync?async=1';
        $resp = cpn_node_request('POST', $url, $token, []);

        if (!empty($resp['ok'])) {
            cpn_activity_log_event('marketplace', 'marketplace.mercadolibre_sync_start', 'Inició sincronización MercadoLibre (async)', 'marketplace', 1, []);
        }

        echo json_encode($resp);
        exit;
    }

    if ($ajax === 'ml_sync_progress') {
        $url = rtrim($base, '/') . '/api/integrations/mercadolibre/sync/progress';
        $resp = cpn_node_request('GET', $url, $token, null);
        echo json_encode($resp);
        exit;
    }

    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => ['message' => 'Acción AJAX inválida']]);
    exit;
}

// — 0) Manejar "Actualizar MP" —
if (isset($_GET['action']) && $_GET['action'] === 'update_mp') {
    $ok = $conn->query("CALL actualizarTituloMarketplace()");
    if ($ok !== false) {
        cpn_activity_log_event('marketplace', 'marketplace.mercadolibre_actualizar_titulo', 'Ejecutó actualizarTituloMarketplace()', 'marketplace', 1, []);
    }
    $qs = $_GET;
    unset($qs['action']);
    header('Location: ' . $_SERVER['PHP_SELF'] . '?' . http_build_query($qs));
    exit;
}


// — 0) Manejar "Actualizar MP" —
if (isset($_GET['action']) && $_GET['action'] === 'update_full_mp') {
    $ok = $conn->query("CALL actualizarMarketplace()");
    if ($ok !== false) {
        cpn_activity_log_event('marketplace', 'marketplace.mercadolibre_actualizar_full', 'Ejecutó actualizarMarketplace()', 'marketplace', 1, []);
    }
    $qs = $_GET;
    unset($qs['action']);
    header('Location: ' . $_SERVER['PHP_SELF'] . '?' . http_build_query($qs));
    exit;
}
// — Preload credenciales & token —
$creds = getCredentials($conn);
refreshTokenIfNeeded($http, $creds, $conn);
$token = $creds['access_token'];

$stage      = $_REQUEST['stage']      ?? 'list';
$product_id = (int)($_REQUEST['product_id'] ?? 0);
$page       = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit      = 50;
$offset     = ($page - 1) * $limit;


// previo a HTML: manejo de POST en select_category
if ($stage  === 'select_category' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    header("Location:?stage=fill_attributes&product_id={$product_id}&category_id={$_POST['category_id']}");
    exit;
}
?>
<?php include '../../templates/header.php'; ?>

<style>
    /* Compacto (solo esta pantalla) */
    #content .container-fluid .table {
        font-size: 12px;
    }

    #content .container-fluid .table th,
    #content .container-fluid .table td {
        padding: .25rem .35rem;
        line-height: 1.15;
    }

    #content .container-fluid .form-control,
    #content .container-fluid .custom-select,
    #content .container-fluid .form-select {
        font-size: 12px !important;
        padding: .2rem .4rem;
        height: calc(1.2em + .5rem + 2px);
    }

    #content .container-fluid .btn {
        font-size: 12px;
        padding: .25rem .5rem;
    }

    #content .container-fluid h1.h3,
    #content .container-fluid .h3 {
        font-size: 1.1rem;
    }

    #content .container-fluid .pagination .page-link {
        font-size: 12px;
        padding: .25rem .5rem;
    }
</style>
<!-- Botones fijos arriba -->
<div class="mb-3">
    <a href="?action=update_full_mp" class="btn btn-success" id="btnMlFullNode">Actualizacion Completa MP</a>
    <a href="?action=update_mp" class="btn btn-success">Actualizar Titulo y Descripcion</a>
    <a href="checklistml.php" class="btn btn-warning">Checklist Conexión</a>
    <a href="https://www.mercadolibre.com.co/publicaciones/listado?page=1&sort=CREATE_LAST"
        target="_blank" class="btn btn-info">Ver publicaciones recientes</a>
</div>

<div class="card shadow mb-3" id="mlNodePanel" style="display:none;">
    <div class="card-header py-2">
        <strong>MercadoLibre (Node)</strong>
    </div>
    <div class="card-body">
        <div class="row">
            <div class="col-md-6">
                <h6 class="text-gray-800">Import (pull + reconciliar)</h6>
                <div><small>Stage:</small> <span id="mlImportStage">-</span></div>
                <div><small>Progreso:</small> <span id="mlImportProg">0/0</span></div>
                <div><small>Inicio:</small> <span id="mlImportStart">-</span></div>
                <div><small>Fin:</small> <span id="mlImportEnd">-</span></div>
                <div><small>Error:</small> <span id="mlImportErr">-</span></div>
            </div>
            <div class="col-md-6">
                <h6 class="text-gray-800">Sync (push a ML)</h6>
                <div><small>Stage:</small> <span id="mlSyncStage">-</span></div>
                <div><small>Progreso:</small> <span id="mlSyncProg">0/0</span></div>
                <div><small>Inicio:</small> <span id="mlSyncStart">-</span></div>
                <div><small>Fin:</small> <span id="mlSyncEnd">-</span></div>
                <div><small>Error:</small> <span id="mlSyncErr">-</span></div>
            </div>
        </div>
        <hr>
        <small class="text-muted">Nota: el job diario de las 4:00am lo corre Node. Este botón dispara el mismo flujo manualmente.</small>
    </div>
</div>

<script>
    (function() {
        function qs(sel) {
            return document.querySelector(sel);
        }

        function setText(id, txt) {
            var el = qs(id);
            if (el) el.textContent = (txt == null || txt === '') ? '-' : String(txt);
        }

        var polling = null;
        var syncStarted = false;

        async function ajax(action) {
            var url = new URL(window.location.href);
            url.searchParams.set('ajax', action);
            url.searchParams.delete('action');
            var resp = await fetch(url.toString(), {
                credentials: 'same-origin'
            });
            return await resp.json();
        }

        function renderImport(p) {
            setText('#mlImportStage', p.stage);
            setText('#mlImportProg', String(p.processed || 0) + '/' + String(p.total || 0));
            setText('#mlImportStart', p.startedAt);
            setText('#mlImportEnd', p.finishedAt);
            setText('#mlImportErr', p.error);
        }

        function renderSync(p) {
            setText('#mlSyncStage', p.stage);
            setText('#mlSyncProg', String(p.processed || 0) + '/' + String(p.total || 0));
            setText('#mlSyncStart', p.startedAt);
            setText('#mlSyncEnd', p.finishedAt);
            setText('#mlSyncErr', p.error);
        }

        async function tick() {
            try {
                var importResp = await ajax('ml_import_progress');
                if (importResp && importResp.ok && importResp.data) {
                    renderImport(importResp.data);

                    // Cuando termine import sin error -> dispara sync
                    if (importResp.data.finishedAt && !importResp.data.error && !syncStarted) {
                        syncStarted = true;
                        await ajax('ml_sync_start');
                    }
                }

                var syncResp = await ajax('ml_sync_progress');
                if (syncResp && syncResp.ok && syncResp.data) {
                    renderSync(syncResp.data);
                }

                // Cuando termine sync -> parar polling
                if (syncResp && syncResp.ok && syncResp.data && syncResp.data.finishedAt) {
                    if (polling) {
                        clearInterval(polling);
                        polling = null;
                    }
                }
            } catch (e) {
                // no-op
            }
        }

        var btn = qs('#btnMlFullNode');
        if (!btn) return;

        btn.addEventListener('click', async function(ev) {
            // Intercepta para correr Node; si falla, deja que siga el link (SP legacy)
            ev.preventDefault();

            qs('#mlNodePanel').style.display = '';
            syncStarted = false;
            setText('#mlImportErr', '-');
            setText('#mlSyncErr', '-');

            try {
                var start = await ajax('ml_import_start');
                if (!start || start.ok !== true) {
                    throw new Error((start && start.error && start.error.message) ? start.error.message : 'No se pudo iniciar import en Node');
                }

                await tick();
                if (polling) clearInterval(polling);
                polling = setInterval(tick, 3000);
            } catch (e) {
                // fallback: ejecuta el SP en PHP (comportamiento anterior)
                window.location.href = btn.getAttribute('href');
            }
        });
    })();
</script>

<?php if ($stage === 'list'): ?>
    <?php

    // --------------------------------------------------
    // Ordenamiento por columna
    $allowedSort = ['titulo' => 'p.tituloPublicacion'];
    $sortKey     = $_GET['sort']   ?? 'titulo';
    $order       = strtoupper($_GET['order'] ?? 'ASC');
    if (!in_array($order, ['ASC', 'DESC'], true)) $order = 'ASC';
    $sortCol     = $allowedSort[$sortKey] ?? $allowedSort['titulo'];
    // Para alternar al hacer clic
    $nextOrder   = $order === 'ASC' ? 'DESC' : 'ASC';
    // --------------------------------------------------

    $cnt = intval($conn->query("
                    SELECT COUNT(*) AS cnt
                      FROM tb_marketplace_productos p
                     WHERE p.idMarketplace=1 AND p.activo=1 AND p.refMP IS NULL AND p.stockPublicacion >0
                ")->fetch_assoc()['cnt']);
    $totalPages = max(1, ceil($cnt / $limit));
    $res = $conn->query("
                    SELECT p.skuMP, p.tituloPublicacion, pr.descripcion, p.id AS pid, 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 AND p.stockPublicacion >0 AND pr.wp_id >0
                     ORDER BY {$sortCol} {$order}
                     LIMIT {$limit} OFFSET {$offset}
                ");
    ?>
    <h1 class="h3 mb-4 text-gray-800">Lista de productos a publicar en Mercadolibre</h1>
    <div class="table-responsive mb-3 ml-wizard">
        <table class="table table-bordered">
            <thead class="thead-light">
                <tr>
                    <th>CPN</th>
                    <th>
                        <?php $arrow = $order === 'ASC' ? '▲' : '▼'; ?>
                        <a href="?stage=list&page=<?= $page ?>&sort=titulo&order=<?= $nextOrder ?>">
                            Título <?= $arrow ?>
                        </a>
                    </th>

                    <th>Descripción</th>
                    <th>Acciones</th>
                </tr>
            </thead>
            <tbody>
                <?php while ($r = $res->fetch_assoc()): ?>
                    <tr>
                        <td><?= htmlspecialchars($r['skuMP'] ?? '-') ?></td>
                        <td><?= htmlspecialchars($r['tituloPublicacion']) ?></td>
                        <td><?= htmlspecialchars($r['descripcion']) ?></td>
                        <td>
                            <a href="?stage=select_category&product_id=<?= $r['pid'] ?>&page=<?= $page ?>"
                                class="btn btn-primary btn-sm mr-1">Publicar</a>
                            <a href="/productos/producto.php?id=<?= $r['idProducto'] ?>"
                                class="btn btn-secondary btn-sm">Ver/Editar</a>
                        </td>
                    </tr>
                <?php endwhile; ?>
            </tbody>
        </table>
    </div>
    <nav>
        <ul class="pagination justify-content-center">
            <?php if ($page > 1): ?>
                <li class="page-item">
                    <a class="page-link" href="?stage=list&page=<?= $page - 1 ?>">&laquo;</a>
                </li>
            <?php endif; ?>
            <?php
            $start = max(1, $page - 2);
            $end   = min($totalPages, $page + 2);
            if ($start > 1): ?>
                <li class="page-item"><a class="page-link" href="?stage=list&page=1">1</a></li>
                <?php if ($start > 2): ?>
                    <li class="page-item disabled"><span class="page-link">…</span></li>
                <?php endif; ?>
            <?php endif;
            for ($p = $start; $p <= $end; $p++):
                $active = $p === $page ? ' active' : '';
            ?>
                <li class="page-item<?= $active ?>">
                    <a class="page-link" href="?stage=list&page=<?= $p ?>"><?= $p ?></a>
                </li>
            <?php endfor;
            if ($end < $totalPages): ?>
                <?php if ($end < $totalPages - 1): ?>
                    <li class="page-item disabled"><span class="page-link">…</span></li>
                <?php endif; ?>
                <li class="page-item">
                    <a class="page-link" href="?stage=list&page=<?= $totalPages ?>"><?= $totalPages ?></a>
                </li>
            <?php endif; ?>
            <?php if ($page < $totalPages): ?>
                <li class="page-item">
                    <a class="page-link" href="?stage=list&page=<?= $page + 1 ?>">&raquo;</a>
                </li>
            <?php endif; ?>
        </ul>
    </nav>

<?php elseif ($stage === 'select_category'): ?>

    <?php
    $row = $conn->query("
                    SELECT p.tituloPublicacion, pr.descripcion, pr.txtMedidas, pr.txtMaterial,  p.idCategoria
                      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'];
    $currentCat = $row['idCategoria'] ?? '';
    $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;
    }
    // 1) Predice categorías:
    $preds = predictCategories($http, $token, $search);

    $candidates = [];
    foreach ($preds as $p) {
        // 2) Filtrar sólo las que admiten variaciones
        $attrs = updateWithRetry($http, 'GET', "/categories/{$p['category_id']}/attributes", $token);
        $hasVariation = false;
        foreach ($attrs as $a) {
            if ((($a['hierarchy'] ?? '') === 'CHILD_PK')
                || ! empty($a['tags']['variation_attribute'])
            ) {
                $hasVariation = true;
                break;
            }
        }
        if (! $hasVariation) {
            continue;
        }

        // 3) Aquí usamos la función corregida
        $ruta = fetchCategoryPath($http, $token, $p['category_id']);
        $candidates[] = [
            'id'   => $p['category_id'],
            'name' => e($ruta)
        ];
    }

    // 4) Fallback por si no queda ninguna
    if (empty($candidates)) {
        $candidates[] = [
            'id'   => CATEGORY_FALLBACK,
            'name' => CATEGORY_FALLBACK . ' (fallback)'
        ];
    }

    ?>

    <div class="step">
        <h2>2) Selecciona categoría</h2>
        <p>
            <strong><?= e($title) ?></strong><br>
            <?= e($desc) ?><br>
            Medidas: <?= e($med) ?> | Material: <?= e($mat) ?>
        </p>
        <form method="get" class="form-inline mb-3">
            <input type="hidden" name="stage" value="select_category">
            <input type="hidden" name="product_id" value="<?= $product_id ?>">
            <input class="form-control mr-2 mb-2" type="text" name="search_query"
                value="<?= e($search) ?>" placeholder="Buscar categoría...">
            <button class="btn btn-primary mb-2">Buscar</button>
        </form>
        <form method="post">
            <input type="hidden" name="product_id" value="<?= $product_id ?>">
            <h2>2) Selecciona categoría</h2>

            <select name="category_id" class="form-control mb-3">
                <?php foreach ($candidates as $c): ?>
                    <option value="<?= $c['id'] ?>" <?= $c['id'] === $currentCat ? 'selected' : '' ?>> <?= $c['name'] ?> </option>
                <?php endforeach; ?>
            </select>

            <button class="btn btn-primary">Siguiente »</button>
        </form>
    </div>

<?php elseif ($stage === 'fill_attributes'): ?>

    <?php
    $category_id = $_REQUEST['category_id'];
    $prod = $conn->query("
                    SELECT p.tituloPublicacion, pr.descripcion, pr.txtMedidas, pr.txtMaterial,
                           p.precioPublicacion, p.stockPublicacion, p.skuMP, p.combo
                      FROM tb_marketplace_productos p
                      JOIN tb_productos pr ON p.idProducto=pr.id
                     WHERE p.id={$product_id}
                ")->fetch_assoc();

    $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);
    $vars = [];
    while ($stmt->fetch()) {
        $vars[] = [
            'id'    => $idVar,
            'sku'   => $vs,
            'price' => $vp,
            'stock' => $vsx,
            'color' => $vc,
            'img'   => str_replace('J:/', 'https://sistema.compranet.com.co/', (string)$vi)
        ];
    }
    $stmt->close();

    try {
        $tech = updateWithRetry($http, 'GET', "/categories/{$category_id}/technical_specs/input", $token, [], 1);
        // —> NEW: carga todos los atributos de la categoría
        // — carga meta-atributos de la categoría —
        $metaAttrs = updateWithRetry($http, 'GET', "/categories/{$category_id}/attributes", $token);

        // — sólo tomo los CHILD_PK válidos —  
        $rawAttrs = [];
        foreach ($metaAttrs as $a) {
            if (($a['hierarchy'] ?? '') === 'CHILD_PK') {
                $rawAttrs[$a['id']] = $a['name'];
            }
        }

        // — reordeno según preferencia —  
        $preferred = ['COLOR', 'EXTERIOR_COLOR'];
        $variantAttrs = [];
        foreach ($preferred as $pid) {
            if (isset($rawAttrs[$pid])) {
                $variantAttrs[$pid] = $rawAttrs[$pid];
                unset($rawAttrs[$pid]);
            }
        }
        // — agrego el resto al final —  
        $variantAttrs += $rawAttrs;
    } catch (RequestException) {
        $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;
    }
    ?>
    <div class="step">
        <h2>3) Completa atributos y variaciones</h2>
        <p>
            <strong><?= e($prod['tituloPublicacion']) ?></strong><br>
            <?= e($prod['descripcion']) ?><br>
            Medidas: <?= e($prod['txtMedidas']) ?> | Material: <?= e($prod['txtMaterial']) ?>
        </p>
        <form method="post">
            <input type="hidden" name="product_id" value="<?= $product_id ?>">
            <input type="hidden" name="category_id" value="<?= e($category_id) ?>">
            <div class="row">
                <?php foreach ($tech['groups'] as $group): ?>
                    <?php foreach ($group['components'] as $comp): ?>
                        <?php foreach ($comp['attributes'] as $attr): ?>
                            <?php
                            $tags = $attr['tags'] ?? [];
                            foreach (['hidden', 'read_only', 'variation_attribute'] as $t) {
                                if ((isset($tags[$t]) && $tags[$t]) || in_array($t, $tags, true)) {
                                    continue 3;
                                }
                            }
                            if (strpos($attr['id'], 'PACKAGE_') === 0) {
                                continue;
                            }
                            $id   = e($attr['id']);
                            $name = e($attr['name']);
                            ?>
                            <div class="form-group col-md-4">
                                <label<?php if (!empty($comp['required'])): ?> class="text-danger font-weight-bold" <?php endif; ?>>
                                    <?= $name ?><?php if (!empty($comp['required'])): ?><span class="text-danger"> *</span><?php endif; ?>
                                </label>

                                <?php if ($id === 'INK_COLOR'): ?>
                                    <input class="form-control" name="attr_INK_COLOR" value="Negra" readonly>
                                <?php elseif ($id === 'SALE_FORMAT'): ?>
                                    <?php if ($prod['combo'] > 1): ?>
                                        <?php
                                        // Por defecto preseleccionamos “Pack” si no viene nada
                                        $selSF = $_REQUEST['attr_SALE_FORMAT'] ?? 'Pack';
                                        ?>
                                        <select class="form-control" name="attr_SALE_FORMAT">
                                            <option value="" <?= $selSF === '' ? 'selected' : '' ?>>No enviar</option>
                                            <option value="Pack" <?= $selSF === 'Pack' ? 'selected' : '' ?>>Pack</option>
                                        </select>
                                    <?php else: ?>
                                        <input type="hidden" name="attr_SALE_FORMAT" value="">
                                    <?php endif; ?>

                                <?php elseif ($id === 'UNITS_PER_PACK'): ?>
                                    <?php if ($prod['combo'] > 1 && ($_REQUEST['attr_SALE_FORMAT'] ?? 'Pack') === 'Pack'): ?>
                                        <input class="form-control"
                                            name="attr_UNITS_PER_PACK"
                                            value="<?= e($_REQUEST['attr_UNITS_PER_PACK'] ?? $prod['combo']) ?>"
                                            placeholder="Unidades por pack (o vacío)">
                                    <?php else: ?>
                                        <input type="hidden" name="attr_UNITS_PER_PACK" value="">
                                    <?php endif; ?>

                                <?php elseif ($id === 'MODEL'): ?>
                                    <input class="form-control" name="attr_MODEL"
                                        value="<?= e($prod['skuMP']) ?>" readonly>
                                <?php elseif ($id === 'BRAND'): ?>
                                    <input class="form-control" name="attr_BRAND"
                                        value="<?= e(DEFAULT_BRAND) ?>" readonly>
                                <?php elseif (!empty($attr['tags']['fixed']) && count($attr['values'] ?? []) === 1): ?>
                                    <?php $only = $attr['values'][0]; ?>
                                    <input class="form-control" readonly value="<?= e($only['name']) ?>">
                                    <input type="hidden" name="attr_<?= $id ?>" value="<?= e($only['id']) ?>">
                                <?php elseif ($comp['component'] === 'COMBO'): ?>
                                    <?php $vals = $attr['values'] ?? []; ?>
                                    <?php if (!empty($comp['ui_config']['allow_filtering'])): ?>
                                        <?php $listId = "lst_{$id}"; ?>
                                        <input list="<?= $listId ?>" name="attr_<?= $id ?>"
                                            class="form-control" placeholder="Filtrar o escribir">
                                        <datalist id="<?= $listId ?>">
                                            <?php foreach ($vals as $v): ?>
                                                <option value="<?= e($v['name']) ?>">
                                                <?php endforeach; ?>
                                        </datalist>
                                    <?php else: ?>
                                        <select class="form-control" name="attr_<?= $id ?>">
                                            <?php if (!($comp['required'] ?? false)): ?>
                                                <option value="">— ninguno —</option>
                                            <?php endif; ?>
                                            <?php foreach ($vals as $v): ?>
                                                <option value="<?= e($v['id']) ?>"><?= e($v['name']) ?></option>
                                            <?php endforeach; ?>
                                        </select>
                                    <?php endif; ?>

                                <?php elseif ($id === 'SPORT_BOTTLE_CAPACITY'): ?>
                                    <?php
                                    // Busca algo como "620ml", "15 oz", etc. en el título o la descripción
                                    $textSearch = $prod['tituloPublicacion'] . ' ' . $prod['descripcion'];
                                    $capacity = '';
                                    if (preg_match('/\b\d+\s?(?:ml|oz)\b/i', $textSearch, $m)) {
                                        $capacity = $m[0];
                                    }
                                    ?>
                                    <input
                                        class="form-control"
                                        name="attr_SPORT_BOTTLE_CAPACITY"
                                        value="<?= e($capacity) ?>">

                                <?php elseif ($comp['component'] === 'TEXT_INPUT'): ?>
                                    <input class="form-control" name="attr_<?= $id ?>">
                                <?php else: ?>
                                    <input class="form-control" name="attr_<?= $id ?>">
                                <?php endif; ?>
                            </div>
                        <?php endforeach; ?>
                    <?php endforeach; ?>
                <?php endforeach; ?>
            </div>

            <h3>Variaciones</h3>

            <div class="form-group col-12 mb-3">
                <label for="chosen_var_attr">Atributo de variación</label>
                <?php
                // determino el seleccionado por defecto
                $sel = $_REQUEST['chosen_var_attr'] ?? null;
                if (!$sel) {
                    // busco el primer preferido
                    foreach ($preferred as $pid) {
                        if (isset($variantAttrs[$pid])) {
                            $sel = $pid;
                            break;
                        }
                    }
                    // si ninguno, tomo el primero del array
                    if (!$sel) {
                        $sel = array_key_first($variantAttrs);
                    }
                }
                ?>
                <select id="chosen_var_attr" name="chosen_var_attr" class="form-control">
                    <option value="">— Vacío (usar COLOR) —</option>
                    <?php foreach ($variantAttrs as $id => $label): ?>
                        <option value="<?= e($id) ?>" <?= $sel === $id ? 'selected' : '' ?>>
                            <?= e($label) ?> (<?= $id ?>)
                        </option>
                    <?php endforeach; ?>
                </select>

            </div>
            <div class="row">
                <?php
                $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):
                ?>
                    <div class="col-md-6">
                        <fieldset class="mb-3 p-2 border">
                            <legend><?= e("SKU {$v['sku']}") ?></legend>
                            <label>Precio:</label>
                            <input class="form-control mb-2" name="var_<?= $i ?>_price"
                                value="<?= e($v['price']) ?>">
                            <label>Stock:</label>
                            <input class="form-control mb-2" name="var_<?= $i ?>_stock"
                                value="<?= e($v['stock']) ?>">
                            <div class="form-group">
                                <label>Color:</label>
                                <input type="text" class="form-control mb-2"
                                    name="var_<?= $i ?>_combo"
                                    value="<?= e($v['color']) ?>" readonly>
                                <input type="hidden" name="var_<?= $i ?>_combo"
                                    value="<?= e($v['color']) ?>">
                            </div>
                        </fieldset>
                    </div>
                <?php endforeach; ?>
            </div>

            <button class="btn btn-primary">Publicar »</button>
        </form>
    </div>

<?php elseif ($stage === 'publish'): ?>

    <?php
    $category_id = $_REQUEST['category_id'];
    $row = $conn->query("
                SELECT p.tituloPublicacion,
                       p.descripcionPublicacion AS descripcion,
                              p.idProducto,
                       pr.txtMedidas,
                       pr.txtMaterial,
                       p.precioPublicacion,
                       p.stockPublicacion,
                       p.skuMP,
                       p.combo
                  FROM tb_marketplace_productos p
                  JOIN tb_productos pr ON p.idProducto=pr.id
                 WHERE p.id={$product_id}
              ")->fetch_assoc();

    // definimos $prod para poder usar $prod['combo'] más abajo
    $prod = $row;
    $title       = $row['tituloPublicacion'];
    $description = $row['descripcion'];
    $price       = $row['precioPublicacion'];
    $stock       = $row['stockPublicacion'];
    $sku_main    = $row['skuMP'];

    $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, $vs, $vp, $vsx, $vi);
    $vars = [];
    while ($stmt->fetch()) {
        $vars[] = [
            'id'    => $idVar,
            'sku'   => $vs,
            'price' => $vp,
            'stock' => $vsx,
            'img'   => str_replace('J:/', 'https://sistema.compranet.com.co/', (string)$vi)
        ];
    }
    $stmt->close();

    $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;
            }
        }
        if (strpos($a['id'], 'PACKAGE_') === 0) {
            return false;
        }
        return true;
    });
    $allowedIds = array_column($allowed, 'id');
    $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;
        // antes
        $topAttrs[] = [
            'id'         => $aid,
            'value_name' => (string)$v
        ];
    }
    $topAttrs = array_values(array_filter($topAttrs, fn($a) => strpos($a['id'], 'PACKAGE_') !== 0));

    // Determinar atributo de variación: primero de variantAttrs, si no existe usar 'COLOR'
    $chosen = $_REQUEST['chosen_var_attr'] ?? null;
    if ($chosen === '') {
        $varAttrId = 'COLOR';
    } elseif ($chosen !== null) {
        $varAttrId = $chosen;
    } else {
        $varAttrId = !empty($variantAttrs)
            ? array_key_first($variantAttrs)
            : 'COLOR';
    }

    // Auto-set sale format y unidades por pack si combo>1
    // — Auto-set sale format y unidades por pack sólo si no vienen como "" —
    if ($prod['combo'] > 1) {
        // SALE_FORMAT
        if (!isset($_GET['attr_SALE_FORMAT']) || $_GET['attr_SALE_FORMAT'] !== '') {
            $value = $_GET['attr_SALE_FORMAT'] ?? 'Pack';
            $topAttrs[] = ['id' => 'SALE_FORMAT', 'value_name' => $value];
        }
        // UNITS_PER_PACK
        if (!isset($_GET['attr_UNITS_PER_PACK']) || $_GET['attr_UNITS_PER_PACK'] !== '') {
            $value = $_GET['attr_UNITS_PER_PACK'] ?? (string)$prod['combo'];
            $topAttrs[] = ['id' => 'UNITS_PER_PACK', 'value_name' => $value];
        }
    }


    $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 = [
        ['id' => 'WARRANTY_TYPE',      'value_id'   => '2230280'],
        ['id' => 'WARRANTY_TIME',      'value_name' => '30 días'],
        ['id' => 'MANUFACTURING_TIME', 'value_name' => '3 días'],
    ];

    $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',
            'free_shipping' => false,
            'local_pick_up' => false,
        ],
        'sale_terms'            => $sale_terms,
        'pictures'              => [],
        'attributes'            => $topAttrs,
        'variations'            => $varsPayload
    ];
    ?>
    <h2>4) Resultado de la publicación</h2>
    <?php
    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'];
            // Subo descripción
            updateWithRetry(
                $http,
                'PUT',
                "/items/{$ml}/description",
                $token,
                ['plain_text' => $description]
            );
            // Actualizo variantes
            $itemData = updateWithRetry($http, 'GET', "/items/{$ml}", $token, [], 1);
            foreach ($itemData['variations'] ?? [] as $var) {
                $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();
            }
            // Actualizo producto
            $u = $conn->prepare("
                            UPDATE tb_marketplace_productos
                               SET refMP = ?, fechaSincronizacion = NOW()
                             WHERE id = ?
                        ");
            $u->bind_param('si', $ml, $product_id);
            $u->execute();
            $u->close();

            cpn_activity_log_event('marketplace', 'marketplace.mercadolibre_publish', 'Publicó producto en MercadoLibre', 'producto', $row['idProducto'] ?? null, [
                'marketplaceProductId' => $product_id,
                'mlItemId' => $ml,
            ]);

            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);

        // 1) toma 'cause' o array vacío
        $causes = $err['cause'] ?? [];

        // 2) si no es array, lo convertimos en uno (o extraemos el mensaje principal)
        if (!is_array($causes)) {
            // si 'cause' viene como string, o no viene, usamos el mensaje principal
            $msgs = [$err['message'] ?? $err['status'] ?? 'Unknown error'];
        } else {
            // si es array, lo iteramos
            $msgs = array_map(function ($c) {
                return $c['message'] ?? $c['field'] ?? json_encode($c);
            }, $causes);
        }

        // ahora puedes mostrarlo sin TypeError
        echo "<p class='error small-text'>❗ " . implode(', ', $msgs) . "</p>";
        echo "<button type='button' class='btn btn-secondary mt-2' onclick='history.back()'>Volver</button>";
    }
    ?>
    <p><a class="btn btn-secondary" href="?stage=list">← Empezar otro</a></p>

<?php else: ?>
    <p class="error">Etapa desconocida.</p>
<?php endif; ?>

</div>
</div>
<?php
// …
ob_end_flush();
?>

<?php include '../../templates/footer.php'; ?>