<?php
namespace Modules\GestorY\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Tenant\TenantContext;
use Modules\GestorY\Services\YamahaScraperService;
use Modules\GestorY\Services\ProdutoIntegrationService;
use Modules\GestorY\Services\ImageSearchService;
use Modules\GestorY\Services\YamahaManualService;
use Modules\GestorY\Services\PurchaseOrderService;
use Gestoreasy\Core\Audit\AuditLogger;

class GestorYController {
    private function getTenantId(): string {
        return TenantContext::getTenantId();
    }

    /**
     * Pesquisa peças no catálogo Yamaha
     */
    public function pesquisarPecas(Request $req): Response {
        $termo = trim($req->get('termo') ?? '');
        $modelo = $req->get('modelo');
        $ano = $req->get('ano');
        
        if (empty($termo)) {
            return new Response(422, ['error' => ['code' => 'termo_required', 'message' => 'Termo de pesquisa é obrigatório']]);
        }

        try {
            $scraper = new YamahaScraperService();
            $pecas = $scraper->pesquisarPecas($termo, $modelo, $ano);
            
            return Response::json([
                'data' => $pecas,
                'total' => count($pecas)
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'scraping_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Obtém detalhes de uma peça
     */
    public function getPecaDetalhes(Request $req): Response {
        $codigo = $req->get('params')[0] ?? null;
        
        if (!$codigo) {
            return new Response(422, ['error' => ['code' => 'codigo_required', 'message' => 'Código da peça é obrigatório']]);
        }

        try {
            $scraper = new YamahaScraperService();
            $peca = $scraper->getPecaDetalhes($codigo);
            
            if (!$peca) {
                return new Response(404, ['error' => ['code' => 'peca_not_found', 'message' => 'Peça não encontrada']]);
            }
            
            // Buscar imagem online se não tiver
            if (empty($peca['imagem_url'])) {
                $imageService = new ImageSearchService();
                $imagem = $imageService->buscarImagem(
                    $codigo,
                    $peca['descricao'] ?? $peca['nome'] ?? null,
                    $peca['marca'] ?? 'Yamaha'
                );
                
                if ($imagem) {
                    $peca['imagem'] = $imagem;
                    $peca['imagem_url'] = $imagem['url'];
                }
            }
            
            return Response::json(['data' => $peca]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'fetch_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Busca imagem de uma peça
     */
    public function buscarImagem(Request $req): Response {
        $codigo = trim($req->get('codigo') ?? '');
        $descricao = $req->get('descricao');
        $marca = $req->get('marca') ?? 'Yamaha';
        
        if (empty($codigo)) {
            return new Response(422, ['error' => ['code' => 'codigo_required', 'message' => 'Código da peça é obrigatório']]);
        }
        
        try {
            $imageService = new ImageSearchService();
            $imagem = $imageService->buscarImagem($codigo, $descricao, $marca);
            
            if (!$imagem) {
                return new Response(404, ['error' => ['code' => 'imagem_not_found', 'message' => 'Imagem não encontrada']]);
            }
            
            // Opcional: baixar e salvar localmente
            $baixar = $req->get('baixar') === 'true';
            if ($baixar) {
                $caminhoLocal = $imageService->baixarESalvarImagem($imagem['url'], $codigo);
                if ($caminhoLocal) {
                    $imagem['caminho_local'] = $caminhoLocal;
                }
            }
            
            return Response::json(['data' => $imagem]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'image_search_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Lista modelos de motocicletas disponíveis
     */
    public function listarModelos(Request $req): Response {
        try {
            $manualService = new YamahaManualService();
            $modelos = $manualService->listarModelos();
            
            return Response::json(['data' => $modelos]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'list_models_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Busca manual de um modelo
     */
    public function buscarManual(Request $req): Response {
        $modelo = trim($req->get('modelo') ?? '');
        
        if (empty($modelo)) {
            return new Response(422, ['error' => ['code' => 'modelo_required', 'message' => 'Modelo é obrigatório']]);
        }
        
        try {
            $manualService = new YamahaManualService();
            $manual = $manualService->buscarManual($modelo);
            
            if (!$manual) {
                return new Response(404, ['error' => ['code' => 'manual_not_found', 'message' => 'Manual não encontrado']]);
            }
            
            return Response::json(['data' => $manual]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'manual_search_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Baixa manual
     */
    public function baixarManual(Request $req): Response {
        $url = trim($req->body['url'] ?? '');
        $modelo = trim($req->body['modelo'] ?? '');
        
        if (empty($url) || empty($modelo)) {
            return new Response(422, ['error' => ['code' => 'params_required', 'message' => 'URL e modelo são obrigatórios']]);
        }
        
        try {
            $manualService = new YamahaManualService();
            $caminho = $manualService->baixarManual($url, $modelo);
            
            if (!$caminho) {
                return new Response(500, ['error' => ['code' => 'download_failed', 'message' => 'Erro ao baixar manual']]);
            }
            
            return Response::json(['data' => ['caminho' => $caminho, 'url' => '/storage/gestory/manuals/' . basename($caminho)]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'download_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Extrai peças de um manual
     */
    public function extrairPecasManual(Request $req): Response {
        $caminho = trim($req->body['caminho'] ?? '');
        
        if (empty($caminho)) {
            return new Response(422, ['error' => ['code' => 'caminho_required', 'message' => 'Caminho do arquivo é obrigatório']]);
        }
        
        try {
            $manualService = new YamahaManualService();
            $pecas = $manualService->extrairPecasDoManual($caminho);
            
            return Response::json(['data' => $pecas]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'extract_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Cria ordem de compra com peças pesquisadas
     */
    public function criarOrdemCompra(Request $req): Response {
        $body = $req->body;
        $pecas = $body['pecas'] ?? [];
        $fornecedorId = !empty($body['fornecedor_id']) ? (int)$body['fornecedor_id'] : null;
        
        if (empty($pecas) || !is_array($pecas)) {
            return new Response(422, ['error' => ['code' => 'pecas_required', 'message' => 'Lista de peças é obrigatória']]);
        }
        
        try {
            $purchaseOrderService = new PurchaseOrderService();
            
            // Buscar imagens para peças que não têm
            $imageService = new ImageSearchService();
            foreach ($pecas as &$peca) {
                if (empty($peca['imagem_url']) && !empty($peca['codigo'])) {
                    $imagem = $imageService->buscarImagem(
                        $peca['codigo'],
                        $peca['descricao'] ?? $peca['nome'] ?? null,
                        $peca['marca'] ?? 'Yamaha'
                    );
                    if ($imagem) {
                        $peca['imagem_url'] = $imagem['url'];
                    }
                }
            }
            
            $ordem = $purchaseOrderService->criarOrdemCompra($pecas, $fornecedorId, $body['dados_adicionais'] ?? []);
            
            AuditLogger::log('create', 'purchase_orders', $ordem['id'], [
                'source' => 'gestory',
                'quantidade_itens' => count($pecas)
            ]);
            
            return Response::json([
                'message' => 'Ordem de compra criada com sucesso',
                'data' => $ordem
            ], 201);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'create_order_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Lista ordens de compra
     */
    public function listarOrdensCompra(Request $req): Response {
        try {
            $purchaseOrderService = new PurchaseOrderService();
            $filtros = [
                'status' => $req->get('status'),
                'fornecedor_id' => $req->get('fornecedor_id')
            ];
            
            $ordens = $purchaseOrderService->listarOrdensCompra($filtros);
            
            return Response::json(['data' => $ordens]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'list_orders_failed', 'message' => $e->getMessage()]]);
        }
    }
    
    /**
     * Obtém detalhes de uma ordem de compra
     */
    public function getOrdemCompra(Request $req): Response {
        $id = (int)($req->get('params')[0] ?? 0);
        
        if ($id <= 0) {
            return new Response(422, ['error' => ['code' => 'id_required', 'message' => 'ID da ordem é obrigatório']]);
        }
        
        try {
            $purchaseOrderService = new PurchaseOrderService();
            $ordem = $purchaseOrderService->getOrdemCompra($id);
            
            if (!$ordem) {
                return new Response(404, ['error' => ['code' => 'order_not_found', 'message' => 'Ordem não encontrada']]);
            }
            
            return Response::json(['data' => $ordem]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'get_order_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Importa peça para o ERP
     */
    public function importarPeca(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        $body = $req->body;
        
        // Pode receber peca_id (se já está no banco) ou dados da peça (para salvar primeiro)
        $pecaId = (int)($body['peca_id'] ?? 0);
        
        try {
            $scraper = new YamahaScraperService();
            $integration = new ProdutoIntegrationService();
            
            // Se não tem peca_id, salvar a peça primeiro
            if ($pecaId <= 0) {
                if (empty($body['codigo_yamaha'])) {
                    return new Response(422, ['error' => ['code' => 'codigo_required', 'message' => 'Código Yamaha é obrigatório']]);
                }
                
                // Salvar peça no banco
                $pecaId = $scraper->salvarPeca([
                    'codigo_yamaha' => $body['codigo_yamaha'],
                    'nome' => $body['nome'] ?? 'Peça Yamaha',
                    'descricao' => $body['descricao'] ?? null,
                    'categoria' => $body['categoria'] ?? null,
                    'preco_yamaha' => isset($body['preco_yamaha']) ? (float)$body['preco_yamaha'] : null,
                    'imagem_url' => $body['imagem_url'] ?? null,
                    'status' => $body['status'] ?? 'disponivel'
                ]);
            }
            
            $dadosCustom = [
                'codigo' => $body['codigo'] ?? null,
                'nome' => $body['nome'] ?? null,
                'preco' => isset($body['preco']) ? (float)$body['preco'] : null,
                'descricao' => $body['descricao'] ?? null,
                'estoque' => isset($body['estoque']) ? (int)$body['estoque'] : null,
                'categoria' => $body['categoria'] ?? null
            ];
            
            $productId = $integration->importarComoProduto($pecaId, $dadosCustom);
            
            AuditLogger::log('create', 'products', $productId, [
                'source' => 'gestory',
                'peca_id' => $pecaId
            ]);
            
            return Response::json([
                'message' => 'Peça importada com sucesso',
                'data' => ['product_id' => $productId, 'peca_id' => $pecaId]
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'import_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Importa múltiplas peças
     */
    public function importarLote(Request $req): Response {
        $body = $req->body;
        $pecaIds = $body['peca_ids'] ?? [];
        
        if (empty($pecaIds) || !is_array($pecaIds)) {
            return new Response(422, ['error' => ['code' => 'peca_ids_required', 'message' => 'Lista de IDs de peças é obrigatória']]);
        }

        try {
            $integration = new ProdutoIntegrationService();
            $resultados = $integration->importarLote($pecaIds, $body['opcoes'] ?? null);
            
            return Response::json([
                'message' => 'Importação em lote concluída',
                'data' => $resultados
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'batch_import_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Obtém configuração
     */
    public function getConfig(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        $stmt = $pdo->prepare('SELECT * FROM gestory_config WHERE tenant_id = ? LIMIT 1');
        $stmt->execute([$tenantId]);
        $config = $stmt->fetch();
        
        if (!$config) {
            // Criar configuração padrão
            $stmt = $pdo->prepare('INSERT INTO gestory_config (tenant_id) VALUES (?)');
            $stmt->execute([$tenantId]);
            $config = [
                'atualizacao_automatica' => false,
                'frequencia_atualizacao' => 24,
                'limite_requisicoes' => 100,
                'timeout_requisicao' => 30
            ];
        }
        
        // Converter JSON fields
        if (!empty($config['modelos_importar'])) {
            $config['modelos_importar'] = json_decode($config['modelos_importar'], true) ?: [];
        }
        
        return Response::json(['data' => $config]);
    }

    /**
     * Atualiza configuração
     */
    public function updateConfig(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        $body = $req->body;
        
        $modelosJson = !empty($body['modelos_importar']) 
            ? json_encode($body['modelos_importar']) 
            : null;
        
        // Verificar se configuração existe
        $checkStmt = $pdo->prepare('SELECT id FROM gestory_config WHERE tenant_id = ? LIMIT 1');
        $checkStmt->execute([$tenantId]);
        $exists = $checkStmt->fetch();
        
        if ($exists) {
            // Atualizar - usar ALTER TABLE dinâmico se campos não existirem
            try {
                $stmt = $pdo->prepare('UPDATE gestory_config SET
                    atualizacao_automatica = ?,
                    frequencia_atualizacao = ?,
                    modelos_importar = ?,
                    limite_requisicoes = ?,
                    timeout_requisicao = ?,
                    user_agent = ?,
                    scraper_type = ?,
                    node_path = ?,
                    api_key = ?,
                    api_base_url = ?
                    WHERE tenant_id = ?');
                
                $stmt->execute([
                    $body['atualizacao_automatica'] ?? false ? 1 : 0,
                    (int)($body['frequencia_atualizacao'] ?? 24),
                    $modelosJson,
                    (int)($body['limite_requisicoes'] ?? 100),
                    (int)($body['timeout_requisicao'] ?? 30),
                    $body['user_agent'] ?? null,
                    $body['scraper_type'] ?? 'curl',
                    $body['node_path'] ?? null,
                    $body['api_key'] ?? null,
                    $body['api_base_url'] ?? null,
                    $tenantId
                ]);
            } catch (\PDOException $e) {
                // Se campos não existem, adicionar e tentar novamente
                if (strpos($e->getMessage(), 'Unknown column') !== false) {
                    // Executar migração de campos
                    $migrationFile = __DIR__ . '/../migrations/002_notificacoes_mysql.sql';
                    if (file_exists($migrationFile)) {
                        $sql = file_get_contents($migrationFile);
                        $pdo->exec($sql);
                    }
                    // Tentar novamente
                    $stmt = $pdo->prepare('UPDATE gestory_config SET
                        atualizacao_automatica = ?,
                        frequencia_atualizacao = ?,
                        modelos_importar = ?,
                        limite_requisicoes = ?,
                        timeout_requisicao = ?,
                        user_agent = ?
                        WHERE tenant_id = ?');
                    $stmt->execute([
                        $body['atualizacao_automatica'] ?? false ? 1 : 0,
                        (int)($body['frequencia_atualizacao'] ?? 24),
                        $modelosJson,
                        (int)($body['limite_requisicoes'] ?? 100),
                        (int)($body['timeout_requisicao'] ?? 30),
                        $body['user_agent'] ?? null,
                        $tenantId
                    ]);
                } else {
                    throw $e;
                }
            }
        } else {
            // Criar nova configuração
            try {
                $stmt = $pdo->prepare('INSERT INTO gestory_config 
                    (tenant_id, atualizacao_automatica, frequencia_atualizacao, modelos_importar, 
                     limite_requisicoes, timeout_requisicao, user_agent, scraper_type, node_path, api_key, api_base_url)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
                $stmt->execute([
                    $tenantId,
                    $body['atualizacao_automatica'] ?? false ? 1 : 0,
                    (int)($body['frequencia_atualizacao'] ?? 24),
                    $modelosJson,
                    (int)($body['limite_requisicoes'] ?? 100),
                    (int)($body['timeout_requisicao'] ?? 30),
                    $body['user_agent'] ?? null,
                    $body['scraper_type'] ?? 'curl',
                    $body['node_path'] ?? null,
                    $body['api_key'] ?? null,
                    $body['api_base_url'] ?? null
                ]);
            } catch (\PDOException $e) {
                // Se campos não existem, criar sem eles
                $stmt = $pdo->prepare('INSERT INTO gestory_config 
                    (tenant_id, atualizacao_automatica, frequencia_atualizacao, modelos_importar, 
                     limite_requisicoes, timeout_requisicao, user_agent)
                    VALUES (?, ?, ?, ?, ?, ?, ?)');
                $stmt->execute([
                    $tenantId,
                    $body['atualizacao_automatica'] ?? false ? 1 : 0,
                    (int)($body['frequencia_atualizacao'] ?? 24),
                    $modelosJson,
                    (int)($body['limite_requisicoes'] ?? 100),
                    (int)($body['timeout_requisicao'] ?? 30),
                    $body['user_agent'] ?? null
                ]);
            }
        }
        
        return Response::json(['message' => 'Configuração atualizada com sucesso']);
    }

    /**
     * Executa atualização automática
     */
    public function executarAtualizacao(Request $req): Response {
        try {
            $scheduler = new \Modules\GestorY\Services\UpdateSchedulerService();
            $resultado = $scheduler->executarAtualizacao();
            
            // Notificar sobre conclusão
            $notif = new \Modules\GestorY\Services\NotificationService();
            $notif->notificarAtualizacaoConcluida(
                $resultado['sucesso'],
                $resultado['erros'],
                $resultado['atualizadas'],
                $resultado['novas']
            );
            
            return Response::json([
                'message' => 'Atualização executada',
                'data' => $resultado
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'update_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Obtém estatísticas
     */
    public function getStats(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        // Total de peças cadastradas
        $stmt = $pdo->prepare('SELECT COUNT(*) as total FROM gestory_pecas WHERE tenant_id = ?');
        $stmt->execute([$tenantId]);
        $totalPecas = (int)$stmt->fetch()['total'];
        
        // Total de peças importadas
        $stmt = $pdo->prepare('SELECT COUNT(*) as total FROM gestory_pecas WHERE tenant_id = ? AND product_id IS NOT NULL');
        $stmt->execute([$tenantId]);
        $totalImportadas = (int)$stmt->fetch()['total'];
        
        // Última atualização
        $stmt = $pdo->prepare('SELECT MAX(ultima_atualizacao) as ultima FROM gestory_pecas WHERE tenant_id = ?');
        $stmt->execute([$tenantId]);
        $ultima = $stmt->fetch()['ultima'];
        
        return Response::json([
            'total_pecas' => $totalPecas,
            'total_importadas' => $totalImportadas,
            'ultima_atualizacao' => $ultima ? date('d/m/Y H:i', strtotime($ultima)) : 'Nunca'
        ]);
    }

    /**
     * Lista logs
     */
    public function listLogs(Request $req): Response {
        $pdo = ConnectionManager::forTenant();
        $tenantId = $this->getTenantId();
        
        $page = (int)($req->get('page') ?? 1);
        $perPage = (int)($req->get('per_page') ?? 20);
        $tipo = $req->get('tipo');
        $offset = ($page - 1) * $perPage;
        
        $sql = 'SELECT * FROM gestory_logs WHERE tenant_id = ?';
        $params = [$tenantId];
        
        if ($tipo) {
            $sql .= ' AND tipo = ?';
            $params[] = $tipo;
        }
        
        $sql .= ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
        $params[] = $perPage;
        $params[] = $offset;
        
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        $logs = $stmt->fetchAll();
        
        // Decodificar JSON
        foreach ($logs as &$log) {
            if (!empty($log['dados_json'])) {
                $log['dados'] = json_decode($log['dados_json'], true);
            }
        }
        
        // Contar total
        $countSql = 'SELECT COUNT(*) as total FROM gestory_logs WHERE tenant_id = ?';
        $countParams = [$tenantId];
        if ($tipo) {
            $countSql .= ' AND tipo = ?';
            $countParams[] = $tipo;
        }
        $stmt = $pdo->prepare($countSql);
        $stmt->execute($countParams);
        $total = (int)$stmt->fetch()['total'];
        
        return Response::json([
            'data' => $logs,
            'page' => $page,
            'per_page' => $perPage,
            'total' => $total,
            'total_pages' => ceil($total / $perPage)
        ]);
    }

    /**
     * Lista notificações
     */
    public function listNotificacoes(Request $req): Response {
        try {
            $notif = new \Modules\GestorY\Services\NotificationService();
            $naoLidas = $notif->listarNaoLidas((int)($req->get('limite') ?? 10));
            
            return Response::json(['data' => $naoLidas]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'notifications_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Marca notificação como lida
     */
    public function marcarNotificacaoLida(Request $req): Response {
        $id = (int)($req->get('params')[0] ?? 0);
        
        if ($id <= 0) {
            return new Response(422, ['error' => ['code' => 'invalid_id', 'message' => 'ID inválido']]);
        }

        try {
            $notif = new \Modules\GestorY\Services\NotificationService();
            $notif->marcarComoLida($id);
            
            return Response::json(['message' => 'Notificação marcada como lida']);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'mark_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Configura API oficial
     */
    public function configurarApi(Request $req): Response {
        $body = $req->body;
        $apiKey = trim($body['api_key'] ?? '');
        $apiBaseUrl = trim($body['api_base_url'] ?? '');
        
        if (empty($apiKey) || empty($apiBaseUrl)) {
            return new Response(422, ['error' => ['code' => 'invalid_params', 'message' => 'API Key e URL são obrigatórios']]);
        }

        try {
            $apiService = new \Modules\GestorY\Services\ApiMigrationService();
            $apiService->configurarApi($apiKey, $apiBaseUrl);
            
            return Response::json(['message' => 'API oficial configurada com sucesso']);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'config_failed', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Migra para API oficial
     */
    public function migrarParaApi(Request $req): Response {
        try {
            $apiService = new \Modules\GestorY\Services\ApiMigrationService();
            $resultado = $apiService->migrarParaApi();
            
            return Response::json([
                'message' => 'Migração concluída',
                'data' => $resultado
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'migration_failed', 'message' => $e->getMessage()]]);
        }
    }
}

