<?php

namespace Modules\Integracoes\MercadoLivre\Services;

use PDO;
use Exception;

/**
 * Serviço para integração com API do Mercado Livre
 */
class MercadoLivreAPIService {
    private PDO $pdo;
    private string $tenantId;
    private string $baseUrl = 'https://api.mercadolivre.com';

    public function __construct(string $tenantId) {
        $this->tenantId = $tenantId;
        $this->pdo = \Gestoreasy\Core\Tenant\ConnectionManager::forTenant($tenantId);
    }

    /**
     * Obtém configuração
     */
    public function getConfig(): array {
        $stmt = $this->pdo->prepare('SELECT * FROM mercadolivre_config WHERE tenant_id = ?');
        $stmt->execute([$this->tenantId]);
        $config = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$config) {
            return [
                'ativo' => false,
                'sincronizar_produtos' => false,
                'sincronizar_pedidos' => false,
                'sincronizar_estoque' => false
            ];
        }

        return $config;
    }

    /**
     * Atualiza configuração
     */
    public function updateConfig(array $dados): void {
        $stmt = $this->pdo->prepare('SELECT id FROM mercadolivre_config WHERE tenant_id = ?');
        $stmt->execute([$this->tenantId]);
        $exists = $stmt->fetch();

        $allowedFields = [
            'app_id', 'client_secret', 'access_token', 'refresh_token', 'token_expires_at',
            'user_id', 'seller_id', 'sincronizar_produtos', 'sincronizar_pedidos',
            'sincronizar_estoque', 'intervalo_sincronizacao_minutos', 'webhook_url',
            'webhook_token', 'ativo'
        ];

        if ($exists) {
            $updates = [];
            $params = [];
            foreach ($allowedFields as $field) {
                if (isset($dados[$field])) {
                    $updates[] = "{$field} = ?";
                    $params[] = $dados[$field];
                }
            }
            if (!empty($updates)) {
                $params[] = $this->tenantId;
                $sql = 'UPDATE mercadolivre_config SET ' . implode(', ', $updates) . ' WHERE tenant_id = ?';
                $stmt = $this->pdo->prepare($sql);
                $stmt->execute($params);
            }
        } else {
            $fields = [];
            $values = [];
            $params = [];
            foreach ($allowedFields as $field) {
                if (isset($dados[$field])) {
                    $fields[] = $field;
                    $values[] = '?';
                    $params[] = $dados[$field];
                }
            }
            if (!empty($fields)) {
                $params[] = $this->tenantId;
                $sql = 'INSERT INTO mercadolivre_config (tenant_id, ' . implode(', ', $fields) . ') VALUES (?, ' . implode(', ', $values) . ')';
                $stmt = $this->pdo->prepare($sql);
                $stmt->execute($params);
            }
        }
    }

    /**
     * Faz requisição à API do Mercado Livre com retry
     */
    private function request(string $endpoint, string $method = 'GET', array $data = []): array {
        $config = $this->getConfig();
        
        if (empty($config['access_token'])) {
            throw new Exception('Access token não configurado');
        }

        // Verificar se token expirou (renovar com 5 minutos de antecedência)
        if (!empty($config['token_expires_at'])) {
            $expiresAt = strtotime($config['token_expires_at']);
            $now = time();
            // Renovar se expirar em menos de 5 minutos
            if ($expiresAt < ($now + 300)) {
                try {
                    $this->refreshToken();
                    $config = $this->getConfig();
                } catch (Exception $e) {
                    error_log("Erro ao renovar token Mercado Livre: " . $e->getMessage());
                    // Se falhar, tentar usar token atual mesmo
                }
            }
        }

        $url = $this->baseUrl . $endpoint;
        
        // Retry com backoff exponencial
        $maxRetries = 3;
        $retryDelay = 1;
        $lastError = null;
        $response = null;

        for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
            $headers = [
                'Authorization: Bearer ' . $config['access_token'],
                'Content-Type: application/json'
            ];

            $ch = curl_init($url);
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_CUSTOMREQUEST => $method,
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_SSL_VERIFYPEER => true
            ]);

            if (!empty($data) && in_array($method, ['POST', 'PUT', 'PATCH'])) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }

            $response = curl_exec($ch);
            $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                $lastError = new Exception("Erro na requisição: {$error}");
                if ($attempt < $maxRetries) {
                    sleep($retryDelay * $attempt);
                    continue;
                }
                throw $lastError;
            }

            if ($statusCode === 401) {
                // Token inválido, tentar renovar
                if ($attempt < $maxRetries) {
                    try {
                        $this->refreshToken();
                        $config = $this->getConfig();
                        sleep($retryDelay);
                        continue;
                    } catch (Exception $e) {
                        throw new Exception("Token inválido e não foi possível renovar: " . $e->getMessage());
                    }
                } else {
                    throw new Exception("Token inválido após tentativas de renovação");
                }
            }

            if ($statusCode >= 400) {
                $errorData = json_decode($response, true);
                $message = $errorData['message'] ?? $errorData['error'] ?? "Erro HTTP {$statusCode}";
                
                // Retry em erros temporários (500, 502, 503, 504)
                if (in_array($statusCode, [500, 502, 503, 504]) && $attempt < $maxRetries) {
                    $lastError = new Exception($message);
                    sleep($retryDelay * $attempt);
                    continue;
                }
                
                throw new Exception($message);
            }

            // Sucesso
            break;
        }

        if ($lastError && !$response) {
            throw $lastError;
        }

        return json_decode($response, true) ?? [];
    }

    /**
     * Troca code por access_token (OAuth 2.0)
     */
    public function handleOAuthCallback(string $code): array {
        $config = $this->getConfig();
        
        if (empty($config['app_id']) || empty($config['client_secret'])) {
            throw new Exception('App ID e Client Secret devem estar configurados');
        }

        $url = $this->baseUrl . '/oauth/token';
        $redirectUri = $this->getRedirectUri();
        
        $data = [
            'grant_type' => 'authorization_code',
            'client_id' => $config['app_id'],
            'client_secret' => $config['client_secret'],
            'code' => $code,
            'redirect_uri' => $redirectUri
        ];

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/x-www-form-urlencoded',
                'Accept: application/json'
            ],
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => true
        ]);

        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new Exception("Erro na requisição: {$error}");
        }

        if ($statusCode !== 200) {
            $errorData = json_decode($response, true);
            $message = $errorData['error_description'] ?? $errorData['error'] ?? "Erro HTTP {$statusCode}";
            throw new Exception($message);
        }

        $tokenData = json_decode($response, true);
        
        if (empty($tokenData['access_token'])) {
            throw new Exception('Access token não recebido');
        }

        // Buscar informações do usuário
        $userInfo = $this->requestWithToken('/users/me', 'GET', [], $tokenData['access_token']);
        
        // Salvar tokens e informações
        $expiresIn = (int)($tokenData['expires_in'] ?? 21600); // 6 horas padrão ML
        $expiresAt = date('Y-m-d H:i:s', time() + $expiresIn);

        $this->updateConfig([
            'access_token' => $tokenData['access_token'],
            'refresh_token' => $tokenData['refresh_token'] ?? null,
            'token_expires_at' => $expiresAt,
            'user_id' => $userInfo['id'] ?? null,
            'seller_id' => $userInfo['seller_reputation']['transactions']['total'] > 0 ? $userInfo['id'] : null
        ]);

        $this->registrarLog('oauth', 'sucesso', 'OAuth autorizado com sucesso', [
            'user_id' => $userInfo['id'] ?? null
        ]);

        return [
            'success' => true,
            'user_id' => $userInfo['id'] ?? null,
            'expires_at' => $expiresAt
        ];
    }

    /**
     * Obtém redirect URI para OAuth
     */
    private function getRedirectUri(): string {
        $baseUrl = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
        return $protocol . '://' . $baseUrl . '/integracoes/mercado-livre/callback';
    }

    /**
     * Atualiza access token
     */
    private function refreshToken(): void {
        $config = $this->getConfig();
        
        if (empty($config['refresh_token'])) {
            throw new Exception('Refresh token não configurado');
        }

        $url = $this->baseUrl . '/oauth/token';
        $data = [
            'grant_type' => 'refresh_token',
            'client_id' => $config['app_id'],
            'client_secret' => $config['client_secret'],
            'refresh_token' => $config['refresh_token']
        ];

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($data),
            CURLOPT_TIMEOUT => 30,
        ]);

        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($statusCode !== 200) {
            throw new Exception('Erro ao atualizar token');
        }

        $tokenData = json_decode($response, true);
        
        $this->updateConfig([
            'access_token' => $tokenData['access_token'],
            'refresh_token' => $tokenData['refresh_token'] ?? $config['refresh_token'],
            'token_expires_at' => date('Y-m-d H:i:s', time() + $tokenData['expires_in'])
        ]);
    }

    /**
     * Faz requisição com token customizado (para OAuth)
     */
    private function requestWithToken(string $endpoint, string $method = 'GET', array $data = [], ?string $token = null): array {
        $url = $this->baseUrl . $endpoint;
        $headers = [
            'Authorization: Bearer ' . ($token ?? ''),
            'Content-Type: application/json'
        ];

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_TIMEOUT => 30,
        ]);

        if (!empty($data) && in_array($method, ['POST', 'PUT', 'PATCH'])) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }

        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new Exception("Erro na requisição: {$error}");
        }

        if ($statusCode >= 400) {
            $errorData = json_decode($response, true);
            throw new Exception($errorData['message'] ?? "Erro HTTP {$statusCode}");
        }

        return json_decode($response, true) ?? [];
    }

    /**
     * Lista produtos do Mercado Livre
     */
    public function listProdutosML(?string $sellerId = null): array {
        $config = $this->getConfig();
        $sellerId = $sellerId ?? $config['seller_id'];
        
        if (!$sellerId) {
            throw new Exception('Seller ID não configurado');
        }

        $endpoint = "/users/{$sellerId}/items/search?status=active";
        return $this->request($endpoint);
    }

    /**
     * Publica produto no Mercado Livre
     */
    public function publicarProduto(int $productId, array $dadosML): array {
        // Buscar produto do ERP
        $stmt = $this->pdo->prepare('SELECT * FROM products WHERE id = ?');
        $stmt->execute([$productId]);
        $produto = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$produto) {
            throw new Exception('Produto não encontrado');
        }

        // Preparar dados para ML
        $itemData = [
            'title' => $dadosML['title'] ?? $produto['nome'],
            'category_id' => $dadosML['category_id'],
            'price' => (float)($dadosML['price'] ?? $produto['preco']),
            'currency_id' => 'BRL',
            'available_quantity' => (int)($dadosML['available_quantity'] ?? $produto['estoque']),
            'buying_mode' => 'buy_it_now',
            'listing_type_id' => $dadosML['listing_type_id'] ?? 'bronze',
            'condition' => $dadosML['condition'] ?? 'new',
            'description' => [
                'plain_text' => $dadosML['description'] ?? $produto['descricao'] ?? ''
            ],
            'pictures' => $dadosML['pictures'] ?? [],
            'attributes' => $dadosML['attributes'] ?? []
        ];

        // Publicar no ML
        $response = $this->request('/items', 'POST', $itemData);

        // Salvar mapeamento
        $stmt = $this->pdo->prepare('
            INSERT INTO mercadolivre_produtos (
                tenant_id, product_id, ml_item_id, ml_sku, status, sincronizado, ultima_sincronizacao
            ) VALUES (?, ?, ?, ?, "ativo", TRUE, NOW())
            ON DUPLICATE KEY UPDATE
                ml_item_id = VALUES(ml_item_id),
                status = "ativo",
                sincronizado = TRUE,
                ultima_sincronizacao = NOW()
        ');
        $stmt->execute([
            $this->tenantId,
            $productId,
            $response['id'],
            $response['seller_sku'] ?? null
        ]);

        $this->registrarLog('produto', 'sucesso', "Produto {$productId} publicado no ML", [
            'ml_item_id' => $response['id'],
            'product_id' => $productId
        ]);

        return $response;
    }

    /**
     * Sincroniza pedidos do Mercado Livre
     */
    public function sincronizarPedidos(): array {
        $config = $this->getConfig();
        $sellerId = $config['seller_id'];
        
        if (!$sellerId) {
            throw new Exception('Seller ID não configurado');
        }

        // Buscar pedidos recentes
        $endpoint = "/orders/search?seller={$sellerId}&order.status=paid";
        $response = $this->request($endpoint);

        $pedidos = $response['results'] ?? [];
        $importados = 0;

        foreach ($pedidos as $mlOrderId) {
            // Buscar detalhes do pedido
            $orderDetails = $this->request("/orders/{$mlOrderId}");
            
            // Verificar se já foi importado
            $stmt = $this->pdo->prepare('
                SELECT id FROM mercadolivre_pedidos
                WHERE tenant_id = ? AND ml_order_id = ?
            ');
            $stmt->execute([$this->tenantId, $mlOrderId]);
            $exists = $stmt->fetch();

            if (!$exists) {
                // Salvar pedido
                $stmt = $this->pdo->prepare('
                    INSERT INTO mercadolivre_pedidos (
                        tenant_id, ml_order_id, status_ml, total,
                        buyer_id, buyer_nickname, dados_json
                    ) VALUES (?, ?, ?, ?, ?, ?, ?)
                ');
                $stmt->execute([
                    $this->tenantId,
                    $mlOrderId,
                    $orderDetails['status'] ?? 'unknown',
                    $orderDetails['total_amount'] ?? 0,
                    $orderDetails['buyer']['id'] ?? null,
                    $orderDetails['buyer']['nickname'] ?? null,
                    json_encode($orderDetails)
                ]);
                $importados++;
            }
        }

        $this->registrarLog('pedido', 'sucesso', "Sincronizados {$importados} novos pedidos", [
            'total_encontrados' => count($pedidos),
            'importados' => $importados
        ]);

        return [
            'total_encontrados' => count($pedidos),
            'importados' => $importados
        ];
    }

    /**
     * Importa pedido do Mercado Livre para o ERP
     */
    public function importarPedido(int $mlOrderId): array {
        $stmt = $this->pdo->prepare('SELECT * FROM mercadolivre_pedidos WHERE ml_order_id = ? AND tenant_id = ?');
        $stmt->execute([$mlOrderId, $this->tenantId]);
        $pedido = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$pedido) {
            throw new Exception('Pedido não encontrado');
        }

        if ($pedido['importado']) {
            throw new Exception('Pedido já foi importado');
        }

        $dados = json_decode($pedido['dados_json'], true);

        // Criar pedido no ERP
        try {
            $this->pdo->beginTransaction();

            // 1. Buscar ou criar cliente
            $clienteId = $this->buscarOuCriarCliente($dados);

            // 2. Gerar número do pedido
            $numero = $this->gerarNumeroPedido();

            // 3. Criar pedido
            $stmt = $this->pdo->prepare('
                INSERT INTO sales_orders (numero, cliente_id, valor_total, status, observacoes)
                VALUES (?, ?, ?, ?, ?)
            ');
            $observacoes = "Pedido importado do Mercado Livre - Order ID: {$pedido['ml_order_id']}";
            $stmt->execute([
                $numero,
                $clienteId,
                $pedido['total'],
                'aberto',
                $observacoes
            ]);
            $salesOrderId = (int)$this->pdo->lastInsertId();

            // 4. Criar itens do pedido
            if (isset($dados['order_items']) && is_array($dados['order_items'])) {
                $this->criarItensPedido($salesOrderId, $dados['order_items']);
            }

            // 5. Atualizar mercadolivre_pedidos com sales_order_id
            $stmt = $this->pdo->prepare('
                UPDATE mercadolivre_pedidos 
                SET sales_order_id = ?, importado = 1 
                WHERE id = ?
            ');
            $stmt->execute([$salesOrderId, $pedido['id']]);

            $this->pdo->commit();

            $this->registrarLog('pedido', 'sucesso', "Pedido {$pedido['ml_order_id']} importado como pedido #{$numero}", [
                'ml_order_id' => $mlOrderId,
                'sales_order_id' => $salesOrderId
            ]);

            return [
                'success' => true,
                'message' => 'Pedido importado com sucesso',
                'sales_order_id' => $salesOrderId,
                'numero' => $numero
            ];
        } catch (\Exception $e) {
            if ($this->pdo->inTransaction()) {
                $this->pdo->rollBack();
            }
            $this->registrarLog('pedido', 'erro', "Erro ao importar pedido {$pedido['ml_order_id']}: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Busca ou cria cliente baseado nos dados do pedido ML
     */
    private function buscarOuCriarCliente(array $dados): int {
        $buyer = $dados['buyer'] ?? [];
        $email = $buyer['email'] ?? null;
        $nickname = $buyer['nickname'] ?? null;

        // Buscar cliente existente por email ou nickname
        if ($email) {
            $stmt = $this->pdo->prepare('SELECT id FROM clients WHERE email = ? LIMIT 1');
            $stmt->execute([$email]);
            $cliente = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($cliente) {
                return (int)$cliente['id'];
            }
        }

        // Criar novo cliente
        $nomeFantasia = $nickname ?: 'Cliente Mercado Livre';
        $tipo = 'PF';

        try {
            $stmt = $this->pdo->prepare('
                INSERT INTO clients (
                    nome, nome_fantasia, razao_social, tipo, 
                    email, inativo, tenant_id
                ) VALUES (?, ?, ?, ?, ?, 0, ?)
            ');
            $stmt->execute([
                $nomeFantasia,
                $nomeFantasia,
                $nomeFantasia,
                $tipo,
                $email,
                $this->tenantId
            ]);
        } catch (\Exception $e) {
            // Tentar sem tenant_id
            $stmt = $this->pdo->prepare('
                INSERT INTO clients (
                    nome, nome_fantasia, razao_social, tipo, 
                    email, inativo
                ) VALUES (?, ?, ?, ?, ?, 0)
            ');
            $stmt->execute([
                $nomeFantasia,
                $nomeFantasia,
                $nomeFantasia,
                $tipo,
                $email
            ]);
        }

        return (int)$this->pdo->lastInsertId();
    }

    /**
     * Gera número sequencial para o pedido
     */
    private function gerarNumeroPedido(): string {
        try {
            $stmt = $this->pdo->query("
                SELECT MAX(CAST(SUBSTRING(numero, 4) AS UNSIGNED)) AS max_seq 
                FROM sales_orders 
                WHERE numero LIKE 'PD-%'
            ");
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            $next = ((int)($row['max_seq'] ?? 0)) + 1;
            return 'PD-' . str_pad((string)$next, 10, '0', STR_PAD_LEFT);
        } catch (\Exception $e) {
            return 'PD-ML-' . time();
        }
    }

    /**
     * Cria itens do pedido no ERP
     */
    private function criarItensPedido(int $salesOrderId, array $items): void {
        $stmt = $this->pdo->prepare('
            INSERT INTO sales_order_items (
                order_id, product_id, quantidade, preco, total
            ) VALUES (?, ?, ?, ?, ?)
        ');

        foreach ($items as $item) {
            // Buscar produto por SKU do ML
            $mlSku = $item['seller_sku'] ?? null;
            $productId = null;

            if ($mlSku) {
                $prodStmt = $this->pdo->prepare('
                    SELECT product_id 
                    FROM mercadolivre_produtos 
                    WHERE ml_sku = ? AND tenant_id = ?
                    LIMIT 1
                ');
                $prodStmt->execute([$mlSku, $this->tenantId]);
                $prod = $prodStmt->fetch(PDO::FETCH_ASSOC);
                if ($prod) {
                    $productId = (int)$prod['product_id'];
                }
            }

            // Se não encontrou por SKU, tentar por item_id
            if (!$productId && isset($item['item']['id'])) {
                $prodStmt = $this->pdo->prepare('
                    SELECT product_id 
                    FROM mercadolivre_produtos 
                    WHERE ml_item_id = ? AND tenant_id = ?
                    LIMIT 1
                ');
                $prodStmt->execute([$item['item']['id'], $this->tenantId]);
                $prod = $prodStmt->fetch(PDO::FETCH_ASSOC);
                if ($prod) {
                    $productId = (int)$prod['product_id'];
                }
            }

            // Se ainda não encontrou, criar produto genérico
            if (!$productId) {
                $productId = $this->criarProdutoGenerico($item);
            }

            $quantidade = (float)($item['quantity'] ?? 1);
            $preco = (float)($item['unit_price'] ?? 0);
            $total = $quantidade * $preco;

            $stmt->execute([
                $salesOrderId,
                $productId,
                $quantidade,
                $preco,
                $total
            ]);
        }
    }

    /**
     * Cria produto genérico quando não encontra mapeamento
     */
    private function criarProdutoGenerico(array $item): int {
        $nome = $item['item']['title'] ?? 'Produto Mercado Livre';
        $sku = $item['seller_sku'] ?? 'ML-' . time();
        $preco = (float)($item['unit_price'] ?? 0);

        try {
            $stmt = $this->pdo->prepare('
                INSERT INTO products (
                    codigo, nome, preco, estoque, ativo, tenant_id
                ) VALUES (?, ?, ?, 0, 1, ?)
            ');
            $stmt->execute([$sku, $nome, $preco, $this->tenantId]);
        } catch (\Exception $e) {
            $stmt = $this->pdo->prepare('
                INSERT INTO products (
                    codigo, nome, preco, estoque, ativo
                ) VALUES (?, ?, ?, 0, 1)
            ');
            $stmt->execute([$sku, $nome, $preco]);
        }
        
        return (int)$this->pdo->lastInsertId();
    }

    /**
     * Sincroniza estoque
     */
    public function sincronizarEstoque(int $productId): void {
        $stmt = $this->pdo->prepare('
            SELECT mp.ml_item_id, p.estoque
            FROM mercadolivre_produtos mp
            INNER JOIN products p ON mp.product_id = p.id
            WHERE mp.tenant_id = ? AND mp.product_id = ?
        ');
        $stmt->execute([$this->tenantId, $productId]);
        $produto = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$produto || empty($produto['ml_item_id'])) {
            throw new Exception('Produto não está publicado no Mercado Livre');
        }

        // Atualizar estoque no ML
        $this->request("/items/{$produto['ml_item_id']}", 'PUT', [
            'available_quantity' => (int)$produto['estoque']
        ]);

        // Atualizar última sincronização
        $stmt = $this->pdo->prepare('
            UPDATE mercadolivre_produtos
            SET ultima_sincronizacao = NOW()
            WHERE tenant_id = ? AND product_id = ?
        ');
        $stmt->execute([$this->tenantId, $productId]);

        $this->registrarLog('estoque', 'sucesso', "Estoque sincronizado para produto {$productId}", [
            'product_id' => $productId,
            'estoque' => $produto['estoque']
        ]);
    }

    /**
     * Sincroniza produtos em lote (síncrono)
     */
    public function sincronizarProdutosEmLote(array $productIds): array {
        $sucesso = 0;
        $falhas = 0;
        $erros = [];

        foreach ($productIds as $productId) {
            try {
                // Sincronizar estoque
                $this->sincronizarEstoque((int)$productId);
                
                // Sincronizar preço se necessário
                $this->sincronizarPreco((int)$productId);
                
                $sucesso++;
            } catch (Exception $e) {
                $falhas++;
                $erros[] = [
                    'product_id' => $productId,
                    'erro' => $e->getMessage()
                ];
                error_log("Erro ao sincronizar produto {$productId}: " . $e->getMessage());
            }
        }

        $this->registrarLog('sincronizacao_lote', 'concluido', "Sincronizados {$sucesso} produtos, {$falhas} falhas", [
            'total' => count($productIds),
            'sucesso' => $sucesso,
            'falhas' => $falhas,
            'erros' => $erros
        ]);

        return [
            'total' => count($productIds),
            'sucesso' => $sucesso,
            'falhas' => $falhas,
            'erros' => $erros
        ];
    }

    /**
     * Sincroniza produtos em fila (assíncrono)
     */
    public function sincronizarProdutosEmFila(array $productIds): array {
        // Criar tabela de fila se não existir
        $this->ensureFilaTable();

        $adicionados = 0;
        foreach ($productIds as $productId) {
            try {
                $stmt = $this->pdo->prepare('
                    INSERT INTO mercadolivre_sync_fila (
                        tenant_id, product_id, tipo, status, created_at
                    ) VALUES (?, ?, "sincronizar", "pendente", NOW())
                    ON DUPLICATE KEY UPDATE
                        status = "pendente",
                        tentativas = 0,
                        created_at = NOW()
                ');
                $stmt->execute([$this->tenantId, (int)$productId]);
                $adicionados++;
            } catch (Exception $e) {
                error_log("Erro ao adicionar produto {$productId} na fila: " . $e->getMessage());
            }
        }

        return [
            'message' => "{$adicionados} produtos adicionados à fila de sincronização",
            'total' => count($productIds),
            'adicionados' => $adicionados,
            'processamento' => 'assincrono'
        ];
    }

    /**
     * Sincroniza preço do produto no ML
     */
    private function sincronizarPreco(int $productId): void {
        $stmt = $this->pdo->prepare('
            SELECT mp.ml_item_id, p.preco
            FROM mercadolivre_produtos mp
            INNER JOIN products p ON mp.product_id = p.id
            WHERE mp.tenant_id = ? AND mp.product_id = ?
        ');
        $stmt->execute([$this->tenantId, $productId]);
        $produto = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$produto || empty($produto['ml_item_id'])) {
            return; // Produto não publicado, pular
        }

        // Atualizar preço no ML
        try {
            $this->request("/items/{$produto['ml_item_id']}", 'PUT', [
                'price' => (float)$produto['preco']
            ]);
        } catch (Exception $e) {
            // Se falhar, apenas logar (não crítico)
            error_log("Erro ao sincronizar preço do produto {$productId}: " . $e->getMessage());
        }
    }

    /**
     * Garante que tabela de fila existe
     */
    private function ensureFilaTable(): void {
        try {
            $this->pdo->exec('
                CREATE TABLE IF NOT EXISTS mercadolivre_sync_fila (
                    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    tenant_id VARCHAR(255) NOT NULL,
                    product_id INT UNSIGNED NOT NULL,
                    tipo VARCHAR(50) NOT NULL DEFAULT "sincronizar",
                    status ENUM("pendente", "processando", "concluido", "erro") NOT NULL DEFAULT "pendente",
                    tentativas INT UNSIGNED NOT NULL DEFAULT 0,
                    ultimo_erro TEXT NULL,
                    created_at DATETIME NOT NULL,
                    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    UNIQUE KEY uk_tenant_product (tenant_id, product_id, tipo),
                    INDEX idx_status (status),
                    INDEX idx_created (created_at)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            ');
        } catch (Exception $e) {
            // Tabela já existe ou erro de permissão
        }
    }

    /**
     * Busca pedido do Mercado Livre
     */
    public function buscarPedidoML(int $mlOrderId): array {
        return $this->request("/orders/{$mlOrderId}");
    }

    /**
     * Busca item do Mercado Livre
     */
    public function buscarItemML(string $itemId): array {
        return $this->request("/items/{$itemId}");
    }

    /**
     * Atualiza status do pedido no ML
     */
    public function atualizarStatusPedido(int $mlOrderId, string $status): array {
        return $this->request("/orders/{$mlOrderId}", 'PUT', [
            'status' => $status
        ]);
    }

    /**
     * Registra log
     */
    private function registrarLog(string $tipo, string $status, string $mensagem, array $detalhes = []): void {
        try {
            $stmt = $this->pdo->prepare('
                INSERT INTO mercadolivre_logs (
                    tenant_id, tipo, status, mensagem, detalhes_json
                ) VALUES (?, ?, ?, ?, ?)
            ');
            $stmt->execute([
                $this->tenantId,
                $tipo,
                $status,
                $mensagem,
                !empty($detalhes) ? json_encode($detalhes) : null
            ]);
        } catch (\Exception $e) {
            // Ignorar erro de log (tabela pode não existir)
            error_log("Erro ao registrar log Mercado Livre: " . $e->getMessage());
        }
    }
}

