<?php
// actualizar_variaciones_seller_sku.php — Script para actualizar el campo SELLER_SKU de variaciones ya creadas en Mercado Libre

require __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/config/db.php';  // Debe definir $conn = new mysqli(...)

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

const CLIENT_ID     = '3658695067033012';
const CLIENT_SECRET = 'GZBg63xJNM9Eeb2cOhF9JwsOEv6vTxo7';
const SITE_ID       = 'MCO';

$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("ERROR: Credenciales no disponibles. Ejecuta authorize.php primero.\n");
    }
    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'     => CLIENT_ID,
            'client_secret' => CLIENT_SECRET,
            '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 $method, string $endpoint, string $token, array $payload = [], int $retries = 3)
{
    $attempt = 0;
    while (true) {
        try {
            usleep(100000);
            $opts = [
                'headers' => [
                    'Authorization' => "Bearer {$token}",
                    'Content-Type'  => 'application/json',
                ],
            ];
            if ($method !== 'GET') {
                $opts['json'] = $payload;
            }
            $resp = match ($method) {
                'GET'  => $http->get($endpoint, $opts),
                'POST' => $http->post($endpoint, $opts),
                default => $http->put($endpoint, $opts),
            };
            return json_decode((string)$resp->getBody(), true);
        } catch (RequestException $ex) {
            $code = $ex->getResponse()?->getStatusCode() ?: 0;
            if (($code === 429 || $code === 503) && $attempt++ < $retries) {
                sleep((int)$ex->getResponse()->getHeaderLine('Retry-After') ?: 5);
                continue;
            }
            throw $ex;
        }
    }
}

// — Inicio del script —

$creds = getCredentials($conn);
refreshTokenIfNeeded($http, $creds, $conn);
$token = $creds['access_token'];

// 1) Seleccionar solo las variaciones conectadas
$sql = <<<SQL
SELECT
  p.refMP           AS itemId,
  v.refMPVariante   AS variationId,
  v.skuMPVariante   AS sellerSku
FROM tb_marketplace_productos p
JOIN tb_marketplace_variantes v
  ON p.id = v.idMarketplaceProducto
WHERE v.conectado = 1
  AND p.conectado = 1
SQL;

$result = $conn->query($sql);
if ($conn->error) {
    die("Error en la consulta de variaciones conectadas: {$conn->error}\n");
}

// 2) Recorrer y actualizar SELLER_SKU
// …tras la consulta $result…

while ($row = $result->fetch_assoc()) {
    $itemId      = $row['itemId'];
    $variationId = (int)$row['variationId'];
    $sellerSku   = $row['sellerSku'];

    // 1) Traer TODAS las variaciones con atributos
    $itemData = updateWithRetry(
        $http,
        'GET',
        "/items/{$itemId}?include_attributes=all",
        $token
    );

    // 2) Reconstruir el array de variaciones: 
    //    • Para la que vamos a actualizar, mantenemos sus atributos menos SELLER_SKU y le ponemos el nuevo
    //    • Para las demás, solo incluimos su id (para conservarlas)
    $variations = [];
    foreach ($itemData['variations'] as $v) {
        if ($v['id'] === $variationId) {
            // conservar los atributos que no sean SELLER_SKU
            $attrs = [];
            foreach ($v['attributes'] ?? [] as $a) {
                if ($a['id'] !== 'SELLER_SKU') {
                    $attrs[] = ['id' => $a['id'], 'value_name' => $a['value_name']];
                }
            }
            // añadir el nuevo SELLER_SKU
            $attrs[] = ['id' => 'SELLER_SKU', 'value_name' => $sellerSku];

            $variations[] = [
                'id'         => $variationId,
                'attributes' => $attrs
            ];
        } else {
            // conservarla sin cambios
            $variations[] = ['id' => $v['id']];
        }
    }

    // 3) Hacer el PUT único al ítem con todas las variaciones
    $payload = ['variations' => $variations];
    try {
        updateWithRetry(
            $http,
            'PUT',
            "/items/{$itemId}",
            $token,
            $payload
        );
        echo "✔ SELLER_SKU actualizado en variación {$variationId} del ítem {$itemId}\n";
    } catch (\Throwable $ex) {
        echo "✖ Error actualizando SELLER_SKU en variación {$variationId}: {$ex->getMessage()}\n";
    }
}



echo "Proceso de actualización de SELLER_SKU completado.\n";
