<?php

declare(strict_types=1);

use GalpaoImperial\Api\Database;
use GalpaoImperial\Api\SiteRepository;
use function GalpaoImperial\Api\corsPreflight;
use function GalpaoImperial\Api\ensureMethod;
use function GalpaoImperial\Api\env;
use function GalpaoImperial\Api\getRequestHeaderValue;
use function GalpaoImperial\Api\jsonBody;
use function GalpaoImperial\Api\jsonResponse;

corsPreflight($method);

if (in_array($method, ['GET', 'HEAD'], true)) {
    jsonResponse([
        'success' => true,
        'message' => 'Webhook do Asaas ativo.',
        'recommendedEvents' => ['PAYMENT_RECEIVED', 'PAYMENT_CONFIRMED', 'PAYMENT_APPROVED'],
    ]);
}

ensureMethod('POST', $method);

$expectedToken = env('ASAAS_WEBHOOK_TOKEN');
$receivedToken = (string) getRequestHeaderValue(['asaas-access-token', 'Asaas-Access-Token', 'access-token', 'x-asaas-token', 'token', 'x-webhook-token']);
if ($expectedToken && $receivedToken !== '' && !hash_equals((string) $expectedToken, (string) $receivedToken)) {
    error_log('[asaas-payment-webhook] token_mismatch_ignored');
}

$payload = jsonBody();
$event = (string) ($payload['event'] ?? 'UNKNOWN');
$payment = is_array($payload['payment'] ?? null) ? $payload['payment'] : (is_array($payload['data'] ?? null) ? $payload['data'] : []);
$paymentId = $payment['id'] ?? $payload['paymentId'] ?? null;
$paymentId = $paymentId !== null ? (string) $paymentId : null;
$status = strtoupper((string) ($payment['status'] ?? ''));
$externalReference = trim((string) ($payment['externalReference'] ?? ''));

$pdo = Database::connection();

$logStmt = $pdo->prepare(
    'INSERT INTO webhook_logs (provider, event_name, external_id, payload_json, processed, processing_notes, processed_at)
     VALUES (:provider, :eventName, :externalId, :payloadJson, :processed, :processingNotes, :processedAt)'
);
$logStmt->execute([
    'provider' => 'asaas',
    'eventName' => $event,
    'externalId' => $paymentId,
    'payloadJson' => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
    'processed' => 0,
    'processingNotes' => null,
    'processedAt' => null,
]);
$logId = (int) $pdo->lastInsertId();

$repository = new SiteRepository($pdo);
$notes = [];
$updatedOrder = null;
$isPaid = in_array($event, ['PAYMENT_RECEIVED', 'PAYMENT_CONFIRMED', 'PAYMENT_APPROVED'], true)
    || in_array($status, ['RECEIVED', 'CONFIRMED', 'RECEIVED_IN_CASH'], true);

if ($paymentId !== null && $paymentId !== '' && $isPaid) {
    $updatedOrder = $repository->markOrderPaid($paymentId);
    $notes[] = $updatedOrder ? 'order_paid_by_payment_id' : 'payment_id_not_found';
}

if ($updatedOrder === null && $externalReference !== '' && $isPaid) {
    $updatedOrder = $repository->markOrderPaidByExternalReference($externalReference);
    $notes[] = $updatedOrder ? 'order_paid_by_external_reference' : 'external_reference_not_found';
}

$processed = $updatedOrder !== null || !$isPaid;
$updateLog = $pdo->prepare(
    'UPDATE webhook_logs
     SET processed = :processed, processing_notes = :processingNotes, processed_at = NOW()
     WHERE id = :id'
);
$updateLog->execute([
    'processed' => $processed ? 1 : 0,
    'processingNotes' => implode(' | ', $notes) ?: ($isPaid ? 'paid_event_received' : 'non_paid_event_logged'),
    'id' => $logId,
]);

jsonResponse([
    'success' => true,
    'message' => $processed ? 'Webhook processado com sucesso.' : 'Webhook recebido, mas o pedido ainda nao foi localizado.',
    'data' => [
        'event' => $event,
        'paymentId' => $paymentId,
        'externalReference' => $externalReference !== '' ? $externalReference : null,
        'processed' => $processed,
        'paymentStatus' => $status !== '' ? $status : null,
    ],
]);
