<?php

declare(strict_types=1);

namespace App\Models;

use App\Enums\UserVerificationType;
use App\Enums\VerificationStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * One account-level trust signal and its current state.
 *
 * @method static Builder<static> verified()
 */
class UserVerification extends Model
{
    use HasFactory;

    /**
     * Status is not fillable: a user must never be able to declare themselves
     * verified. Only the verification services transition it.
     *
     * @var list<string>
     */
    protected $fillable = [
        'type',
        'provider',
        'provider_reference',
        'metadata',
    ];

    /**
     * Evidence locations and reviewer notes stay server-side.
     *
     * @var list<string>
     */
    protected $hidden = [
        'evidence_disk',
        'evidence_path',
        'provider_reference',
    ];

    /**
     * Mirrors the column default, so a new record reads as unverified rather
     * than as null before it is written.
     *
     * @var array<string, mixed>
     */
    protected $attributes = [
        'status' => 'unverified',
    ];

    /** @return array<string, string> */
    protected function casts(): array
    {
        return [
            'type' => UserVerificationType::class,
            'status' => VerificationStatus::class,
            'metadata' => 'array',
            'submitted_at' => 'datetime',
            'verified_at' => 'datetime',
            'expires_at' => 'datetime',
            'reviewed_at' => 'datetime',
        ];
    }

    /** @return BelongsTo<User, $this> */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /** @return BelongsTo<User, $this> */
    public function reviewer(): BelongsTo
    {
        return $this->belongsTo(User::class, 'reviewed_by');
    }

    /** @param  Builder<static>  $query */
    public function scopeVerified(Builder $query): void
    {
        $query->where('status', VerificationStatus::Verified);
    }

    /**
     * Verified and not lapsed. Some verifications (identity documents) expire,
     * and an expired check is not a current one.
     */
    public function isCurrentlyValid(): bool
    {
        if (! $this->status->isVerified()) {
            return false;
        }

        return $this->expires_at === null || $this->expires_at->isFuture();
    }
}
