<?php

namespace App\Services\Photobooth;

use App\Models\Event;
use App\Models\PhotoboothConnectCode;

class PhotoboothConnectCodeService
{
    public function create(Event $event, ?int $expiresInMinutes = null): array
    {
        $length = (int) config('photobooth.connect_code.length', 6);
        $length = max(4, min(8, $length));

        $expiresInMinutes = $expiresInMinutes ?: (int) config('photobooth.connect_code.expires_minutes', 10);
        $expiresInMinutes = max(1, min(120, $expiresInMinutes));

        $code = null;
        $hash = null;
        $max = (10 ** $length) - 1;

        for ($attempts = 0; $attempts < 5; $attempts++) {
            $candidate = str_pad((string) random_int(0, $max), $length, '0', STR_PAD_LEFT);
            $candidateHash = hash('sha256', $candidate);

            $exists = PhotoboothConnectCode::query()
                ->where('code_hash', $candidateHash)
                ->whereNull('redeemed_at')
                ->where('expires_at', '>=', now())
                ->exists();

            if (! $exists) {
                $code = $candidate;
                $hash = $candidateHash;
                break;
            }
        }

        if (! $code || ! $hash) {
            $code = str_pad((string) random_int(0, $max), $length, '0', STR_PAD_LEFT);
            $hash = hash('sha256', $code);
        }

        $expiresAt = now()->addMinutes($expiresInMinutes);

        $record = PhotoboothConnectCode::query()->create([
            'event_id' => $event->getKey(),
            'code_hash' => $hash,
            'expires_at' => $expiresAt,
        ]);

        return [
            'code' => $code,
            'record' => $record,
            'expires_at' => $expiresAt,
        ];
    }

    public function redeem(string $code): ?PhotoboothConnectCode
    {
        $hash = hash('sha256', $code);

        /** @var PhotoboothConnectCode|null $record */
        $record = PhotoboothConnectCode::query()
            ->where('code_hash', $hash)
            ->whereNull('redeemed_at')
            ->where('expires_at', '>=', now())
            ->first();

        if (! $record) {
            return null;
        }

        $record->forceFill([
            'redeemed_at' => now(),
        ])->save();

        return $record;
    }
}
