<?php

namespace App\Controllers;

use Exception;

class WebhookBancoInterController extends BaseController
{
    /**
     * Receber webhook de pagamento do Banco Inter
     * Este endpoint é chamado automaticamente pelo Banco Inter quando há eventos (pagamento, cancelamento, etc)
     */
    public function receberNotificacao(): void
    {
        try {
            // Garantir que o tenant está configurado (webhook vem sem autenticação)
            if (!$this->db) {
                error_log("Webhook Banco Inter - Banco de dados não inicializado");
                $this->response->json(['status' => 'error', 'message' => 'Sistema não inicializado'], 500);
                return;
            }

            // Log da requisição recebida
            $body = file_get_contents('php://input');
            $headers = getallheaders();

            error_log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            error_log("Webhook Banco Inter - Notificação recebida");
            error_log("Headers: " . json_encode($headers));
            error_log("Body: " . $body);
            error_log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");

            $payload = json_decode($body, true);

            if (!$payload) {
                error_log("Webhook Banco Inter - Payload inválido");
                $this->response->json(['status' => 'error', 'message' => 'Payload inválido'], 400);
                return;
            }

            // Estrutura do webhook do Inter:
            // {
            //   "nossoNumero": "90488647895",
            //   "seuNumero": "0000000019",
            //   "dataHoraSituacao": "2025-11-04T15:30:00",
            //   "situacao": "PAGO",
            //   "valorPago": 5.00,
            //   ...
            // }

            $nossoNumero = $payload['nossoNumero'] ?? null;
            $seuNumero = $payload['seuNumero'] ?? null;
            $situacao = $payload['situacao'] ?? null;
            $valorPago = $payload['valorPago'] ?? $payload['valorNominalPago'] ?? 0;
            $dataPagamento = $payload['dataHoraSituacao'] ?? $payload['dataPagamento'] ?? null;

            if (!$nossoNumero && !$seuNumero) {
                error_log("Webhook Banco Inter - Sem nossoNumero ou seuNumero");
                $this->response->json(['status' => 'error', 'message' => 'Dados insuficientes'], 400);
                return;
            }

            // Modo Simples: buscar direto no banco atual
            // Modo Multi-tenant: buscar em todos os tenants
            $conta = null;
            $companyId = null;

            // Verificar se está em modo simples (sem tenant prefix)
            $tenantPrefix = $_ENV['DB_TENANT_PREFIX'] ?? null;
            $isModoSimples = empty($tenantPrefix);

            if ($isModoSimples) {
                // MODO SIMPLES: Buscar direto no banco atual
                error_log("Webhook Banco Inter - Modo SIMPLES detectado");

                if ($seuNumero) {
                    $contaId = (int) ltrim($seuNumero, '0');
                    $stmt = $this->db->prepare("SELECT * FROM contas_receber WHERE id = :id LIMIT 1");
                    $stmt->execute(['id' => $contaId]);
                } else {
                    $stmt = $this->db->prepare("SELECT * FROM contas_receber WHERE nosso_numero_boleto = :nosso_numero LIMIT 1");
                    $stmt->execute(['nosso_numero' => $nossoNumero]);
                }

                $conta = $stmt->fetch();

                if ($conta) {
                    $companyId = $conta['company_id'];
                    error_log("Webhook Banco Inter - Conta encontrada: #{$conta['id']} (MODO SIMPLES)");
                }

            } else {
                // MODO MULTI-TENANT: Buscar em todos os tenants
                error_log("Webhook Banco Inter - Modo MULTI-TENANT detectado");

                $masterDb = $this->tenantManager->getMasterConnection();
                $stmtTenants = $masterDb->query("SELECT * FROM tenants");
                $tenants = $stmtTenants->fetchAll();

                foreach ($tenants as $tenant) {
                    try {
                        $this->tenantManager->setCurrentTenant($tenant);
                        $dbTenant = $this->tenantManager->getTenantConnection();

                        if ($seuNumero) {
                            $contaId = (int) ltrim($seuNumero, '0');
                            $stmt = $dbTenant->prepare("SELECT * FROM contas_receber WHERE id = :id LIMIT 1");
                            $stmt->execute(['id' => $contaId]);
                        } else {
                            $stmt = $dbTenant->prepare("SELECT * FROM contas_receber WHERE nosso_numero_boleto = :nosso_numero LIMIT 1");
                            $stmt->execute(['nosso_numero' => $nossoNumero]);
                        }

                        $contaTemp = $stmt->fetch();

                        if ($contaTemp) {
                            $conta = $contaTemp;
                            $companyId = $conta['company_id'];
                            $this->db = $dbTenant;
                            error_log("Webhook Banco Inter - Conta encontrada: #{$conta['id']} no tenant {$tenant['subdomain']}");
                            break;
                        }
                    } catch (Exception $e) {
                        error_log("Webhook - Erro ao verificar tenant {$tenant['subdomain']}: " . $e->getMessage());
                        continue;
                    }
                }
            }

            if (!$conta) {
                error_log("Webhook Banco Inter - Conta não encontrada (nossoNumero: {$nossoNumero}, seuNumero: {$seuNumero})");
                $this->response->json(['status' => 'error', 'message' => 'Conta não encontrada'], 404);
                return;
            }

            $contaId = $conta['id'];

            // Processar conforme a situação
            if ($situacao === 'PAGO' || $situacao === 'PAGAMENTO_CONFIRMADO') {
                error_log("Webhook Banco Inter - Processando PAGAMENTO da conta #{$contaId}");

                // Calcular novo amount_received e amount_remaining
                $valorPagoFloat = floatval($valorPago);
                $amountReceivedAtual = floatval($conta['amount_received'] ?? 0);
                $novoAmountReceived = $amountReceivedAtual + $valorPagoFloat;
                $totalAmount = floatval($conta['amount']);
                $novoRestante = $totalAmount - $novoAmountReceived;

                $paymentDate = $dataPagamento ? date('Y-m-d H:i:s', strtotime($dataPagamento)) : date('Y-m-d H:i:s');

                // Atualizar conta a receber (SEM transação para garantir que salva)
                // Verificar se existe coluna status_id (módulo de status)
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM contas_receber LIKE 'status_id'");
                $temStatusId = $stmtCheck->rowCount() > 0;

                // Se tiver status_id, buscar o ID do status "pago"
                $statusIdPago = null;
                if ($temStatusId) {
                    $stmtStatus = $this->db->prepare("
                        SELECT id FROM modulo_status
                        WHERE company_id = :company_id
                        AND modulo IN ('entradas', 'contas_receber')
                        AND codigo = 'pago'
                        LIMIT 1
                    ");
                    $stmtStatus->execute(['company_id' => $companyId]);
                    $statusPago = $stmtStatus->fetch();
                    if ($statusPago) {
                        $statusIdPago = $statusPago['id'];
                    }
                }

                // Construir UPDATE dinamicamente
                $sets = [
                    'amount_received = :amount_received',
                    'amount_remaining = :amount_remaining',
                    'payment_date = :payment_date',
                    'boleto_status = :boleto_status',
                    'status = :status',
                    'updated_at = NOW()'
                ];

                $params = [
                    'amount_received' => $novoAmountReceived,
                    'amount_remaining' => $novoRestante,
                    'payment_date' => $paymentDate,
                    'boleto_status' => 'PAGO',
                    'status' => 'pago',
                    'id' => $contaId
                ];

                // Se encontrou status_id, adicionar ao UPDATE
                if ($statusIdPago) {
                    $sets[] = 'status_id = :status_id';
                    $params['status_id'] = $statusIdPago;
                }

                $sql = "UPDATE contas_receber SET " . implode(', ', $sets) . " WHERE id = :id";
                $stmtUpdate = $this->db->prepare($sql);
                $updateResult = $stmtUpdate->execute($params);

                $linhasAfetadas = $stmtUpdate->rowCount();

                error_log("Webhook Banco Inter - UPDATE executado: resultado=" . ($updateResult ? 'true' : 'false') . ", linhas_afetadas={$linhasAfetadas}");
                error_log("Webhook Banco Inter - Conta #{$contaId} atualizada: status=pago, boleto_status=PAGO, recebido=R$ {$novoAmountReceived}" . ($statusIdPago ? ", status_id={$statusIdPago}" : ""));

                // Gerar movimento no fluxo de caixa (DEPOIS do commit principal)
                try {
                    $stmtFluxo = $this->db->prepare("
                        INSERT INTO fluxo_caixa (
                            company_id, tipo, descricao, valor, data_movimento,
                            conta_bancaria_id, created_at
                        ) VALUES (
                            :company_id, 'entrada', :descricao, :valor, :data_movimento,
                            :conta_bancaria_id, NOW()
                        )
                    ");

                    $stmtFluxo->execute([
                        'company_id' => $companyId,
                        'descricao' => 'Recebimento de boleto - ' . ($conta['description'] ?? ''),
                        'valor' => $valorPagoFloat,
                        'data_movimento' => $paymentDate,
                        'conta_bancaria_id' => $conta['conta_bancaria_id'] ?? null
                    ]);

                    error_log("Webhook Banco Inter - Fluxo de caixa gerado com sucesso");
                } catch (Exception $e) {
                    error_log("Webhook Banco Inter - Erro ao gerar fluxo de caixa (NÃO afeta o UPDATE): " . $e->getMessage());
                }

                error_log("Webhook Banco Inter - Pagamento processado com sucesso! Conta #{$contaId}, Valor: R$ {$valorPago}");

                $this->response->json([
                    'status' => 'success',
                    'message' => 'Pagamento processado',
                    'conta_id' => $contaId
                ], 200);

            } elseif ($situacao === 'CANCELADO' || $situacao === 'EXPIRADO') {
                error_log("Webhook Banco Inter - Boleto CANCELADO/EXPIRADO - conta #{$contaId}");

                // Atualizar status do boleto
                $this->db->exec("
                    UPDATE contas_receber
                    SET boleto_status = '{$situacao}', updated_at = NOW()
                    WHERE id = {$contaId} AND company_id = {$companyId}
                ");

                $this->response->json([
                    'status' => 'success',
                    'message' => 'Status atualizado',
                    'situacao' => $situacao
                ], 200);

            } else {
                error_log("Webhook Banco Inter - Situação não processada: {$situacao}");

                $this->response->json([
                    'status' => 'info',
                    'message' => 'Situação não requer ação',
                    'situacao' => $situacao
                ], 200);
            }

        } catch (Exception $e) {
            error_log("Webhook Banco Inter - Erro: " . $e->getMessage());
            error_log("Stack: " . $e->getTraceAsString());

            $this->response->json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }
}

