<?php

namespace App\Models;

/**
 * One row per attendee who registered online for an event — see
 * CreateEventRegistrationsTable's migration comment for why this is a
 * new concept distinct from the one paying client on `events`.
 */
class EventRegistrationModel extends TenantModel
{
    protected $table            = 'event_registrations';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $returnType       = 'object';
    protected $useTimestamps    = true;

    protected $allowedFields = [
        'event_id',
        'guest_id',
        'full_name',
        'phone',
        'email',
        'custom_field_values',
        'registration_code',
        'status',
        'checked_in_at',
    ];

    protected $validationRules = [
        'event_id'  => 'required|integer',
        'full_name' => 'required|max_length[150]',
        'phone'     => 'required|max_length[20]',
        'email'     => 'permit_empty|valid_email|max_length[150]',
    ];

    /**
     * 6-digit numeric, same shape as PasswordResetCodeModel::generateFor()
     * — the closest existing precedent for a short, human-typed code —
     * rather than the longer PREFIX-timestamp-random shape used elsewhere
     * for machine-facing references (payment/invoice numbers), which
     * would be the wrong precedent here since an attendee has to actually
     * read and type this one. Unique per event only (not globally, see
     * the migration's composite unique index), so a rare collision is
     * just retried against that one event's roster.
     */
    public function generateCode(int $eventId): string
    {
        do {
            $code = (string) random_int(100000, 999999);
        } while ($this->where('event_id', $eventId)->where('registration_code', $code)->first() !== null);

        return $code;
    }

    public function findByEventAndCode(int $eventId, string $code): ?object
    {
        return $this->where('event_id', $eventId)->where('registration_code', $code)->first();
    }

    public function forEvent(int $eventId): array
    {
        return $this->where('event_id', $eventId)->orderBy('created_at', 'desc')->findAll();
    }

    public function checkIn(int $id): bool
    {
        return $this->update($id, ['status' => 'checked_in', 'checked_in_at' => date('Y-m-d H:i:s')]);
    }

    /**
     * @return array<int, string|list<string>> field_id => answer (a list of
     *                                          strings for a checkbox field, a plain string otherwise)
     */
    public function decodedCustomFieldValues(object $registration): array
    {
        return empty($registration->custom_field_values) ? [] : (json_decode($registration->custom_field_values, true) ?: []);
    }
}
