<?php

namespace App\Http\Controllers;

use App\Jobs\ProcessRevenueCatWebhook;
use App\Services\Integrations\IntegrationWebhookRecorder;
use App\Support\ApiError;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;

class RevenueCatWebhookController extends Controller
{
    public function __construct(private readonly IntegrationWebhookRecorder $recorder) {}

    public function handle(Request $request): JsonResponse
    {
        $secret = (string) config('services.revenuecat.webhook', '');

        if ($secret === '') {
            Log::error('RevenueCat webhook secret not configured');

            return ApiError::response(
                'webhook_not_configured',
                'Webhook Not Configured',
                'RevenueCat webhook secret is missing.',
                Response::HTTP_INTERNAL_SERVER_ERROR
            );
        }

        $signature = trim((string) $request->header('X-Signature', ''));
        if ($signature === '') {
            return ApiError::response(
                'signature_missing',
                'Signature Missing',
                'The RevenueCat webhook request did not include a signature.',
                Response::HTTP_BAD_REQUEST
            );
        }

        $payload = $request->getContent();
        if (! $this->signatureMatches($payload, $signature, $secret)) {
            return ApiError::response(
                'signature_invalid',
                'Invalid Signature',
                'The webhook signature could not be validated.',
                Response::HTTP_BAD_REQUEST
            );
        }

        $decoded = json_decode($payload, true);
        if (json_last_error() !== JSON_ERROR_NONE || ! is_array($decoded)) {
            Log::warning('RevenueCat webhook received invalid JSON', [
                'error' => json_last_error_msg(),
            ]);

            return ApiError::response(
                'payload_invalid',
                'Invalid Payload',
                'The webhook payload could not be decoded as JSON.',
                Response::HTTP_BAD_REQUEST,
                ['json_error' => json_last_error_msg()]
            );
        }

        $eventId = (string) $request->header('X-Event-Id', '');
        $eventType = data_get($decoded, 'event.type');
        $webhookEvent = $this->recorder->recordReceived(
            'revenuecat',
            $eventId !== '' ? $eventId : null,
            is_string($eventType) && $eventType !== '' ? $eventType : null,
        );

        ProcessRevenueCatWebhook::dispatch(
            $decoded,
            $eventId,
            $webhookEvent->id,
        );

        return response()->json(['status' => 'accepted'], 202);
    }

    private function signatureMatches(string $payload, string $providedSignature, string $secret): bool
    {
        $normalized = preg_replace('/\s+/', '', $providedSignature);
        if (! is_string($normalized)) {
            return false;
        }

        $candidates = [
            base64_encode(hash_hmac('sha1', $payload, $secret, true)),
            base64_encode(hash_hmac('sha256', $payload, $secret, true)),
            hash_hmac('sha1', $payload, $secret),
            hash_hmac('sha256', $payload, $secret),
        ];

        foreach ($candidates as $expected) {
            if (hash_equals($expected, $normalized)) {
                return true;
            }
        }

        return false;
    }
}
