<?php
namespace Modules\GestorY\Services;

use Exception;
use ZipArchive;

/**
 * Serviço para baixar e extrair informações de manuais da Yamaha
 * Site: https://www.yamaha-motor.com.br/manuaisecatalogos
 */
class YamahaManualService {
    private string $baseUrl = 'https://www.yamaha-motor.com.br/manuaisecatalogos';
    private string $downloadDir;
    
    public function __construct() {
        $this->downloadDir = __DIR__ . '/../../../../storage/gestory/manuals/';
        if (!is_dir($this->downloadDir)) {
            mkdir($this->downloadDir, 0755, true);
        }
    }
    
    /**
     * Lista modelos de motocicletas disponíveis
     * 
     * @return array Lista de modelos
     */
    public function listarModelos(): array {
        try {
            $url = $this->baseUrl;
            
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                CURLOPT_SSL_VERIFYPEER => false
            ]);
            
            $html = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            if ($httpCode !== 200 || empty($html)) {
                throw new Exception("Erro ao acessar site da Yamaha: HTTP $httpCode");
            }
            
            // Extrair modelos do HTML
            $modelos = [];
            
            // Buscar por links de modelos (ajustar conforme estrutura do site)
            if (preg_match_all('/<a[^>]+href=["\']([^"\']*modelo[^"\']*|[^"\']*manual[^"\']*)["\'][^>]*>([^<]+)<\/a>/i', $html, $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    $href = $match[1];
                    $nome = trim(strip_tags($match[2]));
                    
                    if (!empty($nome) && !empty($href)) {
                        $modelos[] = [
                            'nome' => $nome,
                            'url' => (strpos($href, 'http') === 0) ? $href : $this->baseUrl . '/' . ltrim($href, '/'),
                            'codigo' => $this->extrairCodigoModelo($nome)
                        ];
                    }
                }
            }
            
            // Se não encontrou por regex, tentar buscar em elementos com classes específicas
            if (empty($modelos)) {
                // Buscar em divs, lis, ou outros elementos que possam conter modelos
                if (preg_match_all('/<div[^>]*class=["\'][^"\']*model[^"\']*["\'][^>]*>([^<]+)<\/div>/i', $html, $matches)) {
                    foreach ($matches[1] as $nome) {
                        $nome = trim(strip_tags($nome));
                        if (!empty($nome)) {
                            $modelos[] = [
                                'nome' => $nome,
                                'url' => $this->baseUrl,
                                'codigo' => $this->extrairCodigoModelo($nome)
                            ];
                        }
                    }
                }
            }
            
            return array_unique($modelos, SORT_REGULAR);
            
        } catch (Exception $e) {
            error_log("Erro ao listar modelos Yamaha: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Busca manual de um modelo específico
     * 
     * @param string $modelo Nome ou código do modelo
     * @return array|null Informações do manual
     */
    public function buscarManual(string $modelo): ?array {
        try {
            $modelos = $this->listarModelos();
            
            // Encontrar modelo correspondente
            $modeloEncontrado = null;
            foreach ($modelos as $m) {
                if (stripos($m['nome'], $modelo) !== false || 
                    stripos($m['codigo'], $modelo) !== false ||
                    stripos($modelo, $m['nome']) !== false) {
                    $modeloEncontrado = $m;
                    break;
                }
            }
            
            if (!$modeloEncontrado) {
                return null;
            }
            
            // Acessar página do modelo
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $modeloEncontrado['url'],
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                CURLOPT_SSL_VERIFYPEER => false
            ]);
            
            $html = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            if ($httpCode !== 200 || empty($html)) {
                return null;
            }
            
            // Extrair links de download de manuais
            $manuais = [];
            if (preg_match_all('/<a[^>]+href=["\']([^"\']*\.(pdf|zip))["\'][^>]*>([^<]*)<\/a>/i', $html, $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    $url = $match[1];
                    $ext = strtolower($match[2]);
                    $nome = trim(strip_tags($match[3]));
                    
                    if (empty($nome)) {
                        $nome = basename($url);
                    }
                    
                    // Tornar URL absoluta
                    if (strpos($url, 'http') !== 0) {
                        $url = $this->baseUrl . '/' . ltrim($url, '/');
                    }
                    
                    $manuais[] = [
                        'nome' => $nome,
                        'url' => $url,
                        'tipo' => $ext,
                        'modelo' => $modeloEncontrado['nome']
                    ];
                }
            }
            
            return [
                'modelo' => $modeloEncontrado,
                'manuais' => $manuais,
                'html' => $html // Para processamento posterior
            ];
            
        } catch (Exception $e) {
            error_log("Erro ao buscar manual: " . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Baixa manual em PDF ou ZIP
     * 
     * @param string $url URL do manual
     * @param string $modelo Nome do modelo
     * @return string|null Caminho local do arquivo
     */
    public function baixarManual(string $url, string $modelo): ?string {
        try {
            $filename = $this->sanitizeFilename($modelo) . '_' . time() . '.' . pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
            $filepath = $this->downloadDir . $filename;
            
            $ch = curl_init($url);
            $fp = fopen($filepath, 'wb');
            curl_setopt_array($ch, [
                CURLOPT_FILE => $fp,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_TIMEOUT => 300, // 5 minutos para downloads grandes
                CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            ]);
            
            curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            fclose($fp);
            
            if ($httpCode !== 200 || !file_exists($filepath)) {
                @unlink($filepath);
                return null;
            }
            
            return $filepath;
            
        } catch (Exception $e) {
            error_log("Erro ao baixar manual: " . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Extrai informações de peças de um manual ZIP
     * 
     * @param string $zipPath Caminho do arquivo ZIP
     * @return array Lista de peças extraídas
     */
    public function extrairPecasDoManual(string $zipPath): array {
        $pecas = [];
        
        try {
            $zip = new ZipArchive();
            if ($zip->open($zipPath) !== TRUE) {
                throw new Exception("Não foi possível abrir o arquivo ZIP");
            }
            
            // Extrair para diretório temporário
            $extractDir = $this->downloadDir . 'extracted/' . basename($zipPath, '.zip') . '/';
            if (!is_dir($extractDir)) {
                mkdir($extractDir, 0755, true);
            }
            
            $zip->extractTo($extractDir);
            $zip->close();
            
            // Processar arquivos extraídos (PDFs, imagens, etc.)
            $files = new \RecursiveIteratorIterator(
                new \RecursiveDirectoryIterator($extractDir),
                \RecursiveIteratorIterator::LEAVES_ONLY
            );
            
            foreach ($files as $file) {
                if ($file->isFile()) {
                    $extension = strtolower($file->getExtension());
                    
                    // Processar imagens (podem conter diagramas de peças)
                    if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
                        $pecas[] = [
                            'tipo' => 'imagem',
                            'arquivo' => $file->getPathname(),
                            'nome' => $file->getFilename()
                        ];
                    }
                    
                    // Processar PDFs (podem conter listas de peças)
                    if ($extension === 'pdf') {
                        // Aqui poderia usar uma biblioteca de PDF para extrair texto
                        $pecas[] = [
                            'tipo' => 'pdf',
                            'arquivo' => $file->getPathname(),
                            'nome' => $file->getFilename()
                        ];
                    }
                }
            }
            
        } catch (Exception $e) {
            error_log("Erro ao extrair peças do manual: " . $e->getMessage());
        }
        
        return $pecas;
    }
    
    /**
     * Extrai código do modelo do nome
     */
    private function extrairCodigoModelo(string $nome): string {
        // Tentar extrair códigos comuns (ex: CG 160, Fazer 250, etc.)
        if (preg_match('/([A-Z]{2,}\s*\d{3,})/i', $nome, $matches)) {
            return strtoupper($matches[1]);
        }
        
        // Se não encontrou, retornar nome sanitizado
        return preg_replace('/[^a-zA-Z0-9]/', '', $nome);
    }
    
    /**
     * Sanitiza nome de arquivo
     */
    private function sanitizeFilename(string $filename): string {
        $filename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $filename);
        $filename = preg_replace('/_+/', '_', $filename);
        return trim($filename, '_');
    }
}

