<?php

namespace App\Modules\Integrations\Platform\Services;

use App\Modules\Integrations\Platform\Repositories\ApiIdempotencyRepository;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

final class ApiIdempotencyService
{
    public function __construct(private readonly ApiIdempotencyRepository $keys) {}

    /**
     * @return array{state:'proceed', id:int}|array{state:'replay', status:int, body:string}|array{state:'conflict'}|array{state:'in_flight'}
     */
    public function begin(Request $request, int $tenantId, int $apiTokenId, string $idempotencyKey, string $rawBody): array
    {
        $method = strtoupper((string) $request->method());
        $pathSig = hash('sha256', $method.'|'.$request->path());
        $bodyHash = hash('sha256', $rawBody);
        $ttl = (int) config('integrations.idempotency.ttl_seconds', 86400);
        $expires = Carbon::now()->addSeconds(max(60, $ttl));

        $res = $this->keys->reserveOrResolve($tenantId, $apiTokenId, $method, $pathSig, $idempotencyKey, $bodyHash, $expires);
        if ($res['state'] === 'reserved') {
            return ['state' => 'proceed', 'id' => (int) $res['id']];
        }
        if ($res['state'] === 'replay') {
            return ['state' => 'replay', 'status' => (int) $res['status'], 'body' => (string) $res['body']];
        }
        if ($res['state'] === 'conflict') {
            return ['state' => 'conflict'];
        }

        return ['state' => 'in_flight'];
    }

    public function complete(int $id, int $httpStatus, string $responseJson): void
    {
        $this->keys->complete($id, $httpStatus, $responseJson);
    }
}
