<?php

namespace App\Services;

use App\Models\ApiClient;
use App\Models\ApiIdempotencyKey;
use Illuminate\Database\QueryException;

class ApiIdempotencyService
{
    public function claim(ApiClient $client, string $idempotencyKey, string $requestHash): ApiIdempotencyKey
    {
        $idempotencyKey = trim($idempotencyKey);

        if ($idempotencyKey === '') {
            throw new \InvalidArgumentException('X-Idempotency-Key is required.');
        }

        try {
            return ApiIdempotencyKey::query()->create([
                'api_client_id' => $client->id,
                'idempotency_key' => $idempotencyKey,
                'request_hash' => $requestHash,
            ]);
        } catch (QueryException $e) {
            if ((string) $e->getCode() !== '23000') {
                throw $e;
            }

            $existing = ApiIdempotencyKey::query()
                ->where('api_client_id', $client->id)
                ->where('idempotency_key', $idempotencyKey)
                ->firstOrFail();

            if ($existing->request_hash !== $requestHash) {
                throw new \RuntimeException('Idempotency key reused with different payload.');
            }

            return $existing;
        }
    }

    public function finalize(ApiIdempotencyKey $key, int $statusCode, array $responseBody): void
    {
        $key->forceFill([
            'response_code' => $statusCode,
            'response_body' => $responseBody,
            'completed_at' => now(),
        ])->save();
    }
}
