<?php

declare(strict_types=1);

namespace App\Models;

use App\DTOs\UserRecoProfileDTO;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * Persisted cache of a user's recommendation preference profile.
 *
 * Schema: user_reco_profiles (user_id PK, json columns, timestamps).
 * Rebuilt by UserPreferenceBuilder → stale when updated_at < now() - TTL.
 */
class UserRecoProfile extends Model
{
    protected $table = 'user_reco_profiles';

    protected $primaryKey = 'user_id';
    public $incrementing  = false;
    protected $keyType    = 'int';

    protected $guarded = [];

    protected $casts = [
        'top_tags_json'              => 'array',
        'top_categories_json'        => 'array',
        'followed_creator_ids_json'  => 'array',
        'tag_weights_json'           => 'array',
        'category_weights_json'      => 'array',
        'disliked_tag_ids_json'      => 'array',
    ];

    // ── Relations ─────────────────────────────────────────────────────────────

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    /**
     * Hydrate a DTO from this model's JSON columns.
     */
    public function toDTO(): UserRecoProfileDTO
    {
        return new UserRecoProfileDTO(
            topTagSlugs:      (array) ($this->top_tags_json             ?? []),
            topCategorySlugs: (array) ($this->top_categories_json       ?? []),
            strongCreatorIds: array_map('intval', (array) ($this->followed_creator_ids_json ?? [])),
            tagWeights:       array_map('floatval', (array) ($this->tag_weights_json         ?? [])),
            categoryWeights:  array_map('floatval', (array) ($this->category_weights_json    ?? [])),
            dislikedTagSlugs: (array) ($this->disliked_tag_ids_json     ?? []),
        );
    }

    /**
     * True when the stored profile is still within the configured TTL.
     */
    public function isFresh(): bool
    {
        if ($this->updated_at === null) {
            return false;
        }

        $ttl = (int) config('recommendations.ttl.user_reco_profile', 6 * 3600);

        return $this->updated_at->addSeconds($ttl)->isFuture();
    }
}
