<?php

namespace Controllers;

use Libs\ResponseLib;
use Models\PaymentModel;
use Psr\Http\Message\ServerRequestInterface;

class WooviWebhookController
{
    private PaymentModel $paymentModel;

    public function __construct()
    {
        $this->paymentModel = new PaymentModel();
    }

    public function __invoke(ServerRequestInterface $request)
    {
        $rawBody = (string)$request->getBody();
        if ($rawBody === '') {
            $rawBody = (string)file_get_contents('php://input');
        }

        $payload = json_decode($rawBody, true);
        if (!is_array($payload)) {
            return ResponseLib::sendFail('Payload inválido', [], 'E_VALIDATE')->withStatus(400);
        }

        $charge = $payload['charge'] ?? null;
        if (!is_array($charge)) {
            return ResponseLib::sendFail('Charge inválida', [], 'E_VALIDATE')->withStatus(400);
        }

        $correlationId = $charge['correlationID'] ?? null;
        $status = $charge['status'] ?? null;

        if (!is_string($correlationId) || $correlationId === '') {
            return ResponseLib::sendFail('correlationID inválido', [], 'E_VALIDATE')->withStatus(400);
        }

        if (!is_string($status) || $status === '') {
            return ResponseLib::sendFail('status inválido', [], 'E_VALIDATE')->withStatus(400);
        }

        if (!$this->isPaidStatus($status)) {
            return ResponseLib::sendOk([
                'correlation_id' => $correlationId,
                'status' => $status,
                'updated' => false,
            ], 'S_WEBHOOK_IGNORED');
        }

        try {
            $payment = $this->paymentModel->findByExternalId($correlationId);
        } catch (\Throwable $e) {
            return ResponseLib::sendFail('Falha ao consultar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
        }

        if (!$payment) {
            return ResponseLib::sendFail('Pagamento não encontrado', ['correlation_id' => $correlationId], 'E_NOT_FOUND')->withStatus(404);
        }

        if ((int)($payment['status_id'] ?? 0) !== PaymentModel::STATUS_PENDING) {
            return ResponseLib::sendOk([
                'payment_id' => (int)$payment['payment_id'],
                'correlation_id' => $correlationId,
                'status' => $status,
                'status_id' => (int)($payment['status_id'] ?? 0),
                'updated' => false,
            ], 'S_PAYMENT_ALREADY_UPDATED');
        }

        try {
            $this->paymentModel->updateStatusId((int)$payment['payment_id'], 1);
        } catch (\Throwable $e) {
            return ResponseLib::sendFail('Falha ao atualizar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
        }

        return ResponseLib::sendOk([
            'payment_id' => (int)$payment['payment_id'],
            'correlation_id' => $correlationId,
            'status' => $status,
            'status_id' => 1,
            'updated' => true,
        ], 'S_PAYMENT_UPDATED');
    }

    private function isPaidStatus(string $status): bool
    {
        $normalized = strtoupper(trim($status));
        return in_array($normalized, ['PAID', 'COMPLETED'], true);
    }
}
