<?php
declare(strict_types=1);

namespace App\Models;

use RedBeanPHP\R;
use RedBeanPHP\OODBBean;

/**
 * Modèle RedBeanPHP minimal pour l'entité « post ».
 *
 * Chaque instance encapsule un bean RedBean (`OODBBean`).  
 * Les opérations CRUD sont déléguées à RedBean, tandis que les
 * getters/setters offrent une API typée.
 */
class Post
{
    /** @var OODBBean le bean réel géré par RedBean */
    private OODBBean $bean;

    /** Constructeur privé – on crée/charge les objets via les factories */
    private function __construct(OODBBean $bean)
    {
        $this->bean = $bean;
    }

    /* -------------------------------------------------
       FACTORIES
       ------------------------------------------------- */

    /** Crée un nouveau post à partir d’un tableau de données */
    public static function make(array $data): self
    {
        $bean = R::dispense('post');
        $bean->title   = $data['title']   ?? '';
        $bean->content = $data['content'] ?? '';
        return new self($bean);
    }

    /** Charge un post existant (lève une exception s’il n’existe pas) */
    public static function find(int $id): self
    {
        $bean = R::load('post', $id);
        if ($bean->id === 0) {
            throw new \RuntimeException("Post {$id} introuvable");
        }
        return new self($bean);
    }

    /** Retourne tous les posts, triés par id décroissant */
    public static function allDesc(): array
    {
        $beans = R::findAll('post', ' ORDER BY id DESC ');
        return array_map(fn(OODBBean $b) => new self($b), $beans);
    }

    /* -------------------------------------------------
       PERSISTENCE
       ------------------------------------------------- */

    /** Enregistre (INSERT ou UPDATE) le bean */
    public function save(): void
    {
        R::store($this->bean);
    }

    /** Supprime le bean de la base */
    public function delete(): void
    {
        R::trash($this->bean);
    }

    /* -------------------------------------------------
       ACCESSEURS / MUTATEURS
       ------------------------------------------------- */

    public function getId(): int      { return (int) $this->bean->id; }
    public function getTitle(): string   { return (string) $this->bean->title; }
    public function getContent(): string { return (string) $this->bean->content; }

    public function setTitle(string $title): void   { $this->bean->title   = $title; }
    public function setContent(string $content): void { $this->bean->content = $content; }

    /* -------------------------------------------------
       MISE À JOUR À PARTIR D'UN TABLEAU
       ------------------------------------------------- */

    /**
     * Met à jour le bean à partir d’un tableau de données.
     *
     * Seuls les champs connus sont pris en compte ; les clés inconnues
     * sont simplement ignorées. Cette méthode facilite l’appel depuis
     * le contrôleur : `$post->updateFromArray($request->getParsedBody());`
     *
     * @param array<string,mixed> $data Données du formulaire
     */
    public function updateFromArray(array $data): void
    {
        // titre
        if (array_key_exists('title', $data)) {
            $this->setTitle((string) $data['title']);
        }

        // contenu
        if (array_key_exists('content', $data)) {
            $this->setContent((string) $data['content']);
        }

        // Si d’autres champs sont ajoutés à l’entité (ex. author, status),
        // il suffit de les gérer ici de la même façon.
    }
}
