<?php
namespace Modules\Fiscal\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Tenant\TenantContext;
use Modules\Fiscal\Services\NFeEntradaService;
use Gestoreasy\Core\Audit\AuditLogger;

/**
 * Controller para receber webhooks de notificações de notas fiscais
 */
class NFeWebhookController {
    private string $tenantId;

    public function __construct() {
        // Tentar obter tenant do header (para webhooks)
        $this->tenantId = $_SERVER['HTTP_X_TENANT_ID'] ?? TenantContext::getTenantId() ?? '';
    }

    /**
     * Endpoint para receber webhook de notificação de NFe
     * POST /api/fiscal/nfe-entrada/webhook
     */
    public function receberWebhook(Request $req): Response {
        try {
            // Obter tenant do header ou query
            $tenantId = $req->header('X-Tenant-Id') ?? $req->query['tenant'] ?? '';
            if (empty($tenantId)) {
                return new Response(400, ['error' => ['code' => 'missing_tenant', 'message' => 'Tenant ID é obrigatório']]);
            }
            $this->tenantId = $tenantId;
            $_SERVER['HTTP_X_TENANT_ID'] = $tenantId;
            
            $body = $req->body;
            $headers = $req->headers ?? [];

            // Validar token de segurança (se configurado)
            $token = $headers['X-Webhook-Token'] ?? $headers['x-webhook-token'] ?? $req->query['token'] ?? '';
            if (!$this->validarToken($token)) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Token inválido ou ausente']]);
            }

            // Processar tipo de notificação
            $tipo = $body['tipo'] ?? 'nfe_recebida';
            
            switch ($tipo) {
                case 'nfe_recebida':
                    return $this->processarNFeRecebida($body);
                case 'nfe_autorizada':
                    return $this->processarNFeAutorizada($body);
                case 'nfe_cancelada':
                    return $this->processarNFeCancelada($body);
                default:
                    return new Response(400, ['error' => ['code' => 'invalid_type', 'message' => 'Tipo de notificação inválido']]);
            }
        } catch (\Exception $e) {
            AuditLogger::log('error', 'nfe_webhook', null, null, ['error' => $e->getMessage()]);
            return new Response(500, ['error' => ['code' => 'webhook_error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Processa notificação de NFe recebida
     */
    private function processarNFeRecebida(array $dados): Response {
        try {
            $chave = $dados['chave_acesso'] ?? '';
            $xml = $dados['xml'] ?? '';

            if (empty($chave) && empty($xml)) {
                return new Response(422, ['error' => ['code' => 'missing_data', 'message' => 'Chave de acesso ou XML é obrigatório']]);
            }

            $service = new NFeEntradaService();

            // Se XML fornecido, processar diretamente
            if (!empty($xml)) {
                $dadosProcessados = $service->processarXml($xml);
                $nfeId = $service->salvarNota($dadosProcessados, 'automatica');
                
                // Processar automaticamente se configurado
                $autoProcessar = $dados['auto_processar'] ?? false;
                if ($autoProcessar) {
                    $service->processarNota($nfeId, true);
                }

                AuditLogger::logCreate('nfe_entrada', $nfeId, ['forma' => 'webhook', 'chave' => $chave]);
                
                return Response::json(['ok' => true, 'id' => $nfeId, 'message' => 'NFe recebida e processada']);
            }

            // Se apenas chave fornecida, consultar SEFAZ
            if (!empty($chave)) {
                try {
                    $sefaService = new \Modules\Fiscal\Services\SEFAZService();
                    $ambiente = $dados['ambiente'] ?? 'producao';
                    $consulta = $sefaService->consultarNFe($chave, $ambiente);
                    
                    if ($consulta['status'] === 'autorizada') {
                        // Tentar baixar XML (se disponível)
                        try {
                            $xml = $sefaService->downloadXml($chave, $ambiente);
                            $dadosProcessados = $service->processarXml($xml);
                            $nfeId = $service->salvarNota($dadosProcessados, 'automatica');
                            
                            // Processar automaticamente se configurado
                            $autoProcessar = $dados['auto_processar'] ?? false;
                            if ($autoProcessar) {
                                $service->processarNota($nfeId, true);
                            }
                            
                            AuditLogger::logCreate('nfe_entrada', $nfeId, ['forma' => 'webhook', 'chave' => $chave]);
                            
                            return Response::json(['ok' => true, 'id' => $nfeId, 'message' => 'NFe consultada e processada']);
                        } catch (\Exception $e) {
                            // Se não conseguir baixar XML, salvar dados da consulta
                            $dadosConsulta = [
                                'chave_acesso' => $chave,
                                'numero' => substr($chave, 25, 9),
                                'serie' => substr($chave, 22, 3),
                                'modelo' => substr($chave, 20, 2),
                                'data_emissao' => date('Y-m-d H:i:s'),
                                'emitente' => ['cnpj' => '', 'nome' => 'Emitente não identificado'],
                                'destinatario' => ['cnpj' => '', 'nome' => 'Destinatário não identificado'],
                                'valores' => ['total' => 0],
                                'itens' => [],
                                'protocolo' => $consulta['protocolo'] ?? null
                            ];
                            
                            return Response::json([
                                'ok' => true, 
                                'message' => 'NFe consultada na SEFAZ. Status: ' . $consulta['status'] . '. XML não disponível para download automático. Use importação manual de XML.',
                                'consulta' => $consulta
                            ]);
                        }
                    } else {
                        return Response::json(['ok' => false, 'message' => 'NFe não autorizada: ' . ($consulta['motivo'] ?? 'Status: ' . $consulta['status']), 'consulta' => $consulta]);
                    }
                } catch (\Exception $e) {
                    return Response::json(['ok' => false, 'message' => 'Erro ao consultar SEFAZ: ' . $e->getMessage()]);
                }
            }

            return new Response(422, ['error' => ['code' => 'missing_data', 'message' => 'Dados insuficientes']]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'process_error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Processa notificação de NFe autorizada
     */
    private function processarNFeAutorizada(array $dados): Response {
        // Similar ao processarNFeRecebida, mas focado em notas já autorizadas
        return $this->processarNFeRecebida($dados);
    }

    /**
     * Processa notificação de NFe cancelada
     */
    private function processarNFeCancelada(array $dados): Response {
        try {
            $chave = $dados['chave_acesso'] ?? '';
            if (empty($chave)) {
                return new Response(422, ['error' => ['code' => 'missing_chave', 'message' => 'Chave de acesso é obrigatória']]);
            }

            $pdo = ConnectionManager::forTenant();
            $stmt = $pdo->prepare('UPDATE nfe_entrada SET status = ? WHERE chave_acesso = ? AND tenant_id = ?');
            $stmt->execute(['cancelada', $chave, $this->tenantId]);

            AuditLogger::logUpdate('nfe_entrada', null, ['acao' => 'cancelar_via_webhook', 'chave' => $chave]);

            return Response::json(['ok' => true, 'message' => 'NFe marcada como cancelada']);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'cancel_error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Valida token do webhook
     */
    private function validarToken(string $token): bool {
        if (empty($token)) {
            // Tentar buscar tenant do header
            $tenantId = $_SERVER['HTTP_X_TENANT_ID'] ?? null;
            if ($tenantId) {
                $this->tenantId = $tenantId;
                $_SERVER['HTTP_X_TENANT_ID'] = $tenantId;
                // Permitir sem token apenas se não houver configuração (desenvolvimento)
                try {
                    $pdo = ConnectionManager::forTenant();
                    $stmt = $pdo->prepare('SELECT webhook_token FROM nfe_entrada_deteccao WHERE tenant_id = ? AND ativo = 1 LIMIT 1');
                    $stmt->execute([$this->tenantId]);
                    $config = $stmt->fetch();
                    // Se não houver token configurado, permitir (desenvolvimento)
                    return empty($config['webhook_token']);
                } catch (\Exception $e) {
                    return false;
                }
            }
            return false;
        }

        // Buscar token configurado
        try {
            $pdo = ConnectionManager::forTenant();
            $stmt = $pdo->prepare('SELECT webhook_token FROM nfe_entrada_deteccao WHERE tenant_id = ? AND ativo = 1 LIMIT 1');
            $stmt->execute([$this->tenantId]);
            $config = $stmt->fetch();

            if ($config && !empty($config['webhook_token'])) {
                return hash_equals($config['webhook_token'], $token);
            }

            // Se não houver token configurado, aceitar (desenvolvimento)
            // Em produção, sempre exigir token quando configurado
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
}

