<?php
namespace Modules\GestorY\Services;

use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Tenant\TenantContext;
use PDO;
use Exception;

/**
 * Serviço para web scraping usando headless browser (Selenium/Puppeteer)
 * Requer Node.js e Puppeteer instalados, ou Selenium com ChromeDriver
 */
class BrowserScraperService {
    private PDO $pdo;
    private string $tenantId;
    private string $baseUrl = 'https://ypec-sss.yamaha-motor.co.jp/ypec/ypec/b2c/html5/app/pt_BR/parts-search/';
    private string $scraperType = 'puppeteer'; // 'puppeteer' ou 'selenium'
    private string $nodePath = '/usr/bin/node'; // Caminho do Node.js
    private string $puppeteerScript = __DIR__ . '/../../../../scripts/puppeteer-scraper.js';

    public function __construct() {
        $this->pdo = ConnectionManager::forTenant();
        $this->tenantId = TenantContext::getTenantId();
        
        // Verificar configuração
        $this->loadConfig();
    }

    /**
     * Carrega configuração do banco
     */
    private function loadConfig(): void {
        try {
            $stmt = $this->pdo->prepare('SELECT scraper_type, node_path FROM gestory_config WHERE tenant_id = ? LIMIT 1');
            $stmt->execute([$this->tenantId]);
            $config = $stmt->fetch();
            
            if ($config) {
                $this->scraperType = $config['scraper_type'] ?? 'puppeteer';
                $this->nodePath = $config['node_path'] ?? '/usr/bin/node';
            }
        } catch (Exception $e) {
            // Usar padrões
        }
    }

    /**
     * Pesquisa usando Puppeteer (Node.js)
     */
    public function pesquisarComPuppeteer(string $termo, ?string $modelo = null, ?string $ano = null): array {
        // Verificar se Node.js está disponível
        if (!$this->isNodeAvailable()) {
            throw new Exception('Node.js não está disponível. Instale Node.js para usar scraping com JavaScript.');
        }

        // Verificar se script Puppeteer existe
        if (!file_exists($this->puppeteerScript)) {
            $this->createPuppeteerScript();
        }

        // Preparar dados para o script
        $data = [
            'termo' => $termo,
            'modelo' => $modelo,
            'ano' => $ano,
            'url' => $this->baseUrl
        ];

        // Criar arquivo temporário com dados
        $tempFile = sys_get_temp_dir() . '/gestory_' . uniqid() . '.json';
        file_put_contents($tempFile, json_encode($data));

        try {
            // Executar script Puppeteer
            $command = escapeshellcmd($this->nodePath) . ' ' . 
                      escapeshellarg($this->puppeteerScript) . ' ' . 
                      escapeshellarg($tempFile);
            
            $output = shell_exec($command . ' 2>&1');
            $result = json_decode($output, true);

            if (!$result || !isset($result['success'])) {
                throw new Exception('Erro ao executar Puppeteer: ' . ($output ?: 'Sem saída'));
            }

            if (!$result['success']) {
                throw new Exception($result['error'] ?? 'Erro desconhecido no Puppeteer');
            }

            return $result['data'] ?? [];
        } finally {
            // Limpar arquivo temporário
            if (file_exists($tempFile)) {
                @unlink($tempFile);
            }
        }
    }

    /**
     * Pesquisa usando Selenium (Python/ChromeDriver)
     */
    public function pesquisarComSelenium(string $termo, ?string $modelo = null, ?string $ano = null): array {
        $pythonScript = __DIR__ . '/../../../../scripts/selenium-scraper.py';
        
        if (!file_exists($pythonScript)) {
            $this->createSeleniumScript();
        }

        $data = [
            'termo' => $termo,
            'modelo' => $modelo,
            'ano' => $ano,
            'url' => $this->baseUrl
        ];

        $tempFile = sys_get_temp_dir() . '/gestory_' . uniqid() . '.json';
        file_put_contents($tempFile, json_encode($data));

        try {
            $command = 'python3 ' . escapeshellarg($pythonScript) . ' ' . escapeshellarg($tempFile);
            $output = shell_exec($command . ' 2>&1');
            $result = json_decode($output, true);

            if (!$result || !isset($result['success'])) {
                throw new Exception('Erro ao executar Selenium: ' . ($output ?: 'Sem saída'));
            }

            if (!$result['success']) {
                throw new Exception($result['error'] ?? 'Erro desconhecido no Selenium');
            }

            return $result['data'] ?? [];
        } finally {
            if (file_exists($tempFile)) {
                @unlink($tempFile);
            }
        }
    }

    /**
     * Verifica se Node.js está disponível
     */
    private function isNodeAvailable(): bool {
        $output = shell_exec(escapeshellcmd($this->nodePath) . ' --version 2>&1');
        return !empty($output) && strpos($output, 'v') === 0;
    }

    /**
     * Cria script Puppeteer se não existir
     */
    private function createPuppeteerScript(): void {
        $dir = dirname($this->puppeteerScript);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        $script = <<<'JS'
const puppeteer = require('puppeteer');
const fs = require('fs');

const inputFile = process.argv[2];
if (!inputFile) {
    console.log(JSON.stringify({ success: false, error: 'Arquivo de entrada não fornecido' }));
    process.exit(1);
}

const data = JSON.parse(fs.readFileSync(inputFile, 'utf8'));

(async () => {
    let browser;
    try {
        browser = await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
        
        const page = await browser.newPage();
        await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
        
        // Construir URL
        const params = new URLSearchParams({ searchTerm: data.termo, lang: 'pt_BR' });
        if (data.modelo) params.append('model', data.modelo);
        if (data.ano) params.append('year', data.ano);
        
        const url = data.url + 'index.html?' + params.toString();
        await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
        
        // Aguardar carregamento de dados (ajustar selector conforme necessário)
        await page.waitForTimeout(3000);
        
        // Extrair dados da página
        const pecas = await page.evaluate(() => {
            const results = [];
            
            // Tentar diferentes seletores (ajustar conforme estrutura real do site)
            const items = document.querySelectorAll('.part-item, tr.part-row, [data-part-code]');
            
            items.forEach(item => {
                const codigo = item.querySelector('.part-code, [data-part-code], td:first-child')?.textContent?.trim();
                const nome = item.querySelector('.part-name, [data-part-name], td:nth-child(2)')?.textContent?.trim();
                const preco = item.querySelector('.price, [data-price], td:nth-child(3)')?.textContent?.trim();
                const img = item.querySelector('img')?.src;
                
                if (codigo && nome) {
                    results.push({
                        codigo_yamaha: codigo,
                        nome: nome,
                        preco_yamaha: preco ? parseFloat(preco.replace(/[^\d,.]/g, '').replace(',', '.')) : null,
                        imagem_url: img || null,
                        status: 'disponivel'
                    });
                }
            });
            
            // Se não encontrou com seletores, tentar extrair de JSON embutido
            if (results.length === 0) {
                const scripts = Array.from(document.querySelectorAll('script'));
                scripts.forEach(script => {
                    const content = script.textContent || '';
                    const match = content.match(/var\s+partsData\s*=\s*(\[.*?\]);/s);
                    if (match) {
                        try {
                            const data = JSON.parse(match[1]);
                            data.forEach(item => {
                                if (item.code && item.name) {
                                    results.push({
                                        codigo_yamaha: item.code,
                                        nome: item.name,
                                        preco_yamaha: item.price || null,
                                        imagem_url: item.image || null,
                                        status: item.status || 'disponivel'
                                    });
                                }
                            });
                        } catch (e) {}
                    }
                });
            }
            
            return results;
        });
        
        console.log(JSON.stringify({ success: true, data: pecas }));
    } catch (error) {
        console.log(JSON.stringify({ 
            success: false, 
            error: error.message || 'Erro desconhecido no Puppeteer' 
        }));
        process.exit(1);
    } finally {
        if (browser) {
            await browser.close();
        }
    }
})();
JS;

        file_put_contents($this->puppeteerScript, $script);
    }

    /**
     * Cria script Selenium se não existir
     */
    private function createSeleniumScript(): void {
        $pythonScript = __DIR__ . '/../../../../scripts/selenium-scraper.py';
        $dir = dirname($pythonScript);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        $script = <<<'PY'
#!/usr/bin/env python3
import json
import sys
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

input_file = sys.argv[1] if len(sys.argv) > 1 else None
if not input_file:
    print(json.dumps({"success": False, "error": "Arquivo de entrada não fornecido"}))
    sys.exit(1)

with open(input_file, 'r', encoding='utf-8') as f:
    data = json.load(f)

try:
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Construir URL
    params = {'searchTerm': data['termo'], 'lang': 'pt_BR'}
    if data.get('modelo'):
        params['model'] = data['modelo']
    if data.get('ano'):
        params['year'] = data['ano']
    
    url = data['url'] + 'index.html?' + '&'.join([f"{k}={v}" for k, v in params.items()])
    driver.get(url)
    
    # Aguardar carregamento
    time.sleep(3)
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "body")))
    
    # Extrair dados
    pecas = []
    items = driver.find_elements(By.CSS_SELECTOR, '.part-item, tr.part-row, [data-part-code]')
    
    for item in items:
        try:
            codigo_elem = item.find_element(By.CSS_SELECTOR, '.part-code, [data-part-code], td:first-child')
            nome_elem = item.find_element(By.CSS_SELECTOR, '.part-name, [data-part-name], td:nth-child(2)')
            
            codigo = codigo_elem.text.strip()
            nome = nome_elem.text.strip()
            
            if codigo and nome:
                preco = None
                try:
                    preco_elem = item.find_element(By.CSS_SELECTOR, '.price, [data-price], td:nth-child(3)')
                    preco_str = preco_elem.text.strip()
                    preco = float(preco_str.replace(',', '.').replace('R$', '').strip())
                except:
                    pass
                
                pecas.append({
                    'codigo_yamaha': codigo,
                    'nome': nome,
                    'preco_yamaha': preco,
                    'status': 'disponivel'
                })
        except:
            continue
    
    driver.quit()
    print(json.dumps({"success": True, "data": pecas}))
    
except Exception as e:
    print(json.dumps({"success": False, "error": str(e)}))
    sys.exit(1)
PY;

        file_put_contents($pythonScript, $script);
        chmod($pythonScript, 0755);
    }
}

