<?php

namespace Modules\Integracoes\WooCommerce\Services;

use PDO;
use Exception;

/**
 * Serviço para integração com API REST do WooCommerce
 */
class WooCommerceAPIService {
    private PDO $pdo;
    private string $tenantId;
    private string $baseUrl = '';

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

    public function getConfig(): array {
        $stmt = $this->pdo->prepare('SELECT * FROM woocommerce_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
            ];
        }

        // Não retornar secrets
        unset($config['consumer_secret']);
        unset($config['webhook_secret']);

        return $config;
    }

    public function updateConfig(array $dados): void {
        $stmt = $this->pdo->prepare('SELECT id FROM woocommerce_config WHERE tenant_id = ?');
        $stmt->execute([$this->tenantId]);
        $exists = $stmt->fetch();

        $allowedFields = [
            'store_url', 'consumer_key', 'consumer_secret',
            'sincronizar_produtos', 'sincronizar_pedidos',
            'sincronizar_estoque', 'intervalo_sincronizacao_minutos',
            'webhook_url', 'webhook_secret', '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 woocommerce_config SET ' . implode(', ', $updates) . ' WHERE tenant_id = ?';
                $stmt = $this->pdo->prepare($sql);
                $stmt->execute($params);
            }
        } else {
            $fields = ['tenant_id'];
            $values = ['?'];
            $params = [$this->tenantId];
            foreach ($allowedFields as $field) {
                if (isset($dados[$field])) {
                    $fields[] = $field;
                    $values[] = '?';
                    $params[] = $dados[$field];
                }
            }
            $sql = 'INSERT INTO woocommerce_config (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
        }
    }

    /**
     * Faz requisição à API REST do WooCommerce
     */
    private function request(string $endpoint, string $method = 'GET', array $data = []): array {
        $config = $this->getConfig();
        
        if (empty($config['store_url']) || empty($config['consumer_key']) || empty($config['consumer_secret'])) {
            throw new Exception('Configuração do WooCommerce incompleta');
        }

        $url = rtrim($config['store_url'], '/') . '/wp-json/wc/v3/' . ltrim($endpoint, '/');
        
        // Autenticação Basic Auth (Consumer Key:Consumer Secret)
        $auth = base64_encode($config['consumer_key'] . ':' . $config['consumer_secret']);

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Basic ' . $auth,
                'Content-Type: application/json'
            ],
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_TIMEOUT => 30
        ]);

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

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

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

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

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

    public function listProdutos(): array {
        $stmt = $this->pdo->prepare('
            SELECT wp.*, p.nome, p.codigo, p.preco, p.estoque
            FROM woocommerce_produtos wp
            LEFT JOIN products p ON p.id = wp.product_id
            WHERE wp.tenant_id = ?
            ORDER BY wp.updated_at DESC
        ');
        $stmt->execute([$this->tenantId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function sincronizarProdutos(?int $productId = null): array {
        try {
            // Buscar produtos do WooCommerce
            $page = 1;
            $perPage = 100;
            $allProducts = [];

            do {
                $products = $this->request("products?page={$page}&per_page={$perPage}");
                if (empty($products)) break;
                $allProducts = array_merge($allProducts, $products);
                $page++;
            } while (count($products) === $perPage);

            $sincronizados = 0;

            foreach ($allProducts as $wcProduct) {
                // Buscar produto no ERP por SKU
                $sku = $wcProduct['sku'] ?? null;
                if (!$sku) continue;

                $stmt = $this->pdo->prepare('SELECT id FROM products WHERE codigo = ? LIMIT 1');
                $stmt->execute([$sku]);
                $product = $stmt->fetch(PDO::FETCH_ASSOC);

                if ($product) {
                    // Atualizar mapeamento
                    $stmt = $this->pdo->prepare('
                        INSERT INTO woocommerce_produtos (tenant_id, product_id, wc_product_id, wc_sku, status, sincronizado, ultima_sincronizacao)
                        VALUES (?, ?, ?, ?, ?, 1, NOW())
                        ON DUPLICATE KEY UPDATE
                            wc_product_id = VALUES(wc_product_id),
                            status = VALUES(status),
                            sincronizado = 1,
                            ultima_sincronizacao = NOW()
                    ');
                    $stmt->execute([
                        $this->tenantId,
                        $product['id'],
                        $wcProduct['id'],
                        $sku,
                        $wcProduct['status'] ?? 'draft'
                    ]);
                    $sincronizados++;
                }
            }

            $this->log('produto', 'sucesso', "Sincronizados {$sincronizados} produtos");

            return ['sincronizados' => $sincronizados, 'total' => count($allProducts)];
        } catch (\Exception $e) {
            $this->log('produto', 'erro', "Erro ao sincronizar produtos: " . $e->getMessage());
            throw $e;
        }
    }

    public function publicarProduto(int $productId): array {
        $stmt = $this->pdo->prepare('SELECT * FROM products WHERE id = ? AND tenant_id = ?');
        $stmt->execute([$productId, $this->tenantId]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);

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

        // Verificar se já está mapeado
        $stmt = $this->pdo->prepare('SELECT wc_product_id FROM woocommerce_produtos WHERE product_id = ? AND tenant_id = ?');
        $stmt->execute([$productId, $this->tenantId]);
        $mapping = $stmt->fetch(PDO::FETCH_ASSOC);

        $wcProductData = [
            'name' => $product['nome'],
            'type' => 'simple',
            'regular_price' => (string)$product['preco'],
            'stock_quantity' => (int)$product['estoque'],
            'manage_stock' => true,
            'sku' => $product['codigo'] ?: 'ERP-' . $productId
        ];

        if ($mapping && $mapping['wc_product_id']) {
            // Atualizar produto existente
            $response = $this->request("products/{$mapping['wc_product_id']}", 'PUT', $wcProductData);
        } else {
            // Criar novo produto
            $response = $this->request('products', 'POST', $wcProductData);
            
            // Salvar mapeamento
            $stmt = $this->pdo->prepare('
                INSERT INTO woocommerce_produtos (tenant_id, product_id, wc_product_id, wc_sku, status, sincronizado, ultima_sincronizacao)
                VALUES (?, ?, ?, ?, ?, 1, NOW())
            ');
            $stmt->execute([
                $this->tenantId,
                $productId,
                $response['id'],
                $wcProductData['sku'],
                $response['status'] ?? 'publish'
            ]);
        }

        $this->log('produto', 'sucesso', "Produto {$productId} publicado no WooCommerce");

        return ['success' => true, 'wc_product_id' => $response['id']];
    }

    public function listPedidos(): array {
        $stmt = $this->pdo->prepare('
            SELECT wp.*, so.numero as sales_order_numero
            FROM woocommerce_pedidos wp
            LEFT JOIN sales_orders so ON so.id = wp.sales_order_id
            WHERE wp.tenant_id = ?
            ORDER BY wp.created_at DESC
            LIMIT 100
        ');
        $stmt->execute([$this->tenantId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function sincronizarPedidos(): array {
        try {
            $config = $this->getConfig();
            if (!$config['ativo']) {
                throw new Exception('Integração não está ativa');
            }

            // Buscar pedidos do WooCommerce
            $page = 1;
            $perPage = 100;
            $allOrders = [];

            do {
                $orders = $this->request("orders?page={$page}&per_page={$perPage}&status=processing,completed");
                if (empty($orders)) break;
                $allOrders = array_merge($allOrders, $orders);
                $page++;
            } while (count($orders) === $perPage);

            $sincronizados = 0;

            foreach ($allOrders as $wcOrder) {
                $stmt = $this->pdo->prepare('
                    INSERT INTO woocommerce_pedidos (
                        tenant_id, wc_order_id, status_wc, total, currency,
                        customer_id, customer_email, customer_name, dados_json, sincronizado
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
                    ON DUPLICATE KEY UPDATE
                        status_wc = VALUES(status_wc),
                        total = VALUES(total),
                        dados_json = VALUES(dados_json),
                        sincronizado = 1,
                        updated_at = NOW()
                ');
                $stmt->execute([
                    $this->tenantId,
                    $wcOrder['id'],
                    $wcOrder['status'],
                    $wcOrder['total'],
                    $wcOrder['currency'] ?? 'BRL',
                    $wcOrder['customer_id'] ?? null,
                    $wcOrder['billing']['email'] ?? null,
                    ($wcOrder['billing']['first_name'] ?? '') . ' ' . ($wcOrder['billing']['last_name'] ?? ''),
                    json_encode($wcOrder)
                ]);
                $sincronizados++;
            }

            $this->log('pedido', 'sucesso', "Sincronizados {$sincronizados} pedidos");

            return ['sincronizados' => $sincronizados, 'total' => count($allOrders)];
        } catch (\Exception $e) {
            $this->log('pedido', 'erro', "Erro ao sincronizar pedidos: " . $e->getMessage());
            throw $e;
        }
    }

    public function importarPedido(int $wcOrderId): array {
        $stmt = $this->pdo->prepare('SELECT * FROM woocommerce_pedidos WHERE wc_order_id = ? AND tenant_id = ?');
        $stmt->execute([$wcOrderId, $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 (similar ao TikTok)
        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 WooCommerce - Order ID: {$pedido['wc_order_id']}";
            $stmt->execute([
                $numero,
                $clienteId,
                $pedido['total'],
                'aberto',
                $observacoes
            ]);
            $salesOrderId = (int)$this->pdo->lastInsertId();

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

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

            $this->pdo->commit();

            $this->log('pedido', 'sucesso', "Pedido {$pedido['wc_order_id']} importado como pedido #{$numero}");

            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->log('pedido', 'erro', "Erro ao importar pedido {$pedido['wc_order_id']}: " . $e->getMessage());
            throw $e;
        }
    }

    public function sincronizarEstoque(int $productId): array {
        $stmt = $this->pdo->prepare('SELECT * FROM products WHERE id = ? AND tenant_id = ?');
        $stmt->execute([$productId, $this->tenantId]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);

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

        $stmt = $this->pdo->prepare('SELECT wc_product_id FROM woocommerce_produtos WHERE product_id = ? AND tenant_id = ?');
        $stmt->execute([$productId, $this->tenantId]);
        $wcProduct = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$wcProduct) {
            throw new Exception('Produto não está publicado no WooCommerce');
        }

        $this->request("products/{$wcProduct['wc_product_id']}", 'PUT', [
            'stock_quantity' => (int)$product['estoque']
        ]);

        $this->log('estoque', 'sucesso', "Estoque sincronizado para produto {$productId}");

        return ['success' => true];
    }

    public function processarWebhook(array $dados): void {
        $action = $dados['action'] ?? '';
        $resource = $dados['resource'] ?? '';

        if ($action === 'created' && $resource === 'order') {
            $orderId = $dados['id'] ?? null;
            if ($orderId) {
                // Buscar pedido do WooCommerce
                $order = $this->request("orders/{$orderId}");
                
                // Salvar/atualizar no banco
                $stmt = $this->pdo->prepare('
                    INSERT INTO woocommerce_pedidos (
                        tenant_id, wc_order_id, status_wc, total, currency,
                        customer_id, customer_email, customer_name, dados_json, sincronizado
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
                    ON DUPLICATE KEY UPDATE
                        status_wc = VALUES(status_wc),
                        total = VALUES(total),
                        dados_json = VALUES(dados_json),
                        updated_at = NOW()
                ');
                $stmt->execute([
                    $this->tenantId,
                    $order['id'],
                    $order['status'],
                    $order['total'],
                    $order['currency'] ?? 'BRL',
                    $order['customer_id'] ?? null,
                    $order['billing']['email'] ?? null,
                    ($order['billing']['first_name'] ?? '') . ' ' . ($order['billing']['last_name'] ?? ''),
                    json_encode($order)
                ]);
            }
        }

        $this->log('webhook', 'sucesso', "Webhook processado: {$action} - {$resource}");
    }

    private function buscarOuCriarCliente(array $dados): int {
        $email = $dados['billing']['email'] ?? null;
        $nome = trim(($dados['billing']['first_name'] ?? '') . ' ' . ($dados['billing']['last_name'] ?? ''));

        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
        $tipo = 'PF';
        $nomeFantasia = $nome ?: 'Cliente WooCommerce';
        $telefone = $dados['billing']['phone'] ?? null;

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

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

    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-WC-' . time();
        }
    }

    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) {
            $sku = $item['sku'] ?? null;
            $productId = null;

            if ($sku) {
                $prodStmt = $this->pdo->prepare('
                    SELECT product_id 
                    FROM woocommerce_produtos 
                    WHERE wc_sku = ? AND tenant_id = ?
                    LIMIT 1
                ');
                $prodStmt->execute([$sku, $this->tenantId]);
                $prod = $prodStmt->fetch(PDO::FETCH_ASSOC);
                if ($prod) {
                    $productId = (int)$prod['product_id'];
                } else {
                    // Buscar por código
                    $prodStmt = $this->pdo->prepare('SELECT id FROM products WHERE codigo = ? LIMIT 1');
                    $prodStmt->execute([$sku]);
                    $prod = $prodStmt->fetch(PDO::FETCH_ASSOC);
                    if ($prod) {
                        $productId = (int)$prod['id'];
                    }
                }
            }

            if (!$productId) {
                $productId = $this->criarProdutoGenerico($item);
            }

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

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

    private function criarProdutoGenerico(array $item): int {
        $nome = $item['name'] ?? 'Produto WooCommerce';
        $sku = $item['sku'] ?? 'WC-' . time();
        $preco = (float)($item['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();
    }

    private function log(string $tipo, string $status, string $mensagem, array $detalhes = []): void {
        $stmt = $this->pdo->prepare('
            INSERT INTO woocommerce_logs (tenant_id, tipo, status, mensagem, detalhes_json)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            $tipo,
            $status,
            $mensagem,
            json_encode($detalhes)
        ]);
    }
}

