<?php
declare(strict_types=1);

namespace App\Model\Entity;

use Authentication\PasswordHasher\DefaultPasswordHasher;
use Cake\ORM\Entity;

/**
 * User Entity
 *
 * @property int $id
 * @property string $email
 * @property string $password
 * @property string $first_name
 * @property string $last_name
 * @property string|null $avatar
 * @property string|null $phone
 * @property \Cake\I18n\Date|null $date_of_birth
 * @property string|null $role
 * @property \Cake\I18n\DateTime $created
 * @property \Cake\I18n\DateTime $modified
 *
 * @property string $user_full_display
 * @property string $full_name
 *
 * @property \App\Model\Entity\BlogArticle[] $blog_articles
 * @property \App\Model\Entity\Order[] $orders
 * @property \App\Model\Entity\UserPreference[] $user_preferences
 */
class User extends Entity
{
    /**
     * Fields that can be mass assigned using newEntity() or patchEntity().
     *
     * Note: for security, created/modified fields are not directly assignable.
     *
     * @var array<string, bool>
     */
    protected array $_accessible = [
        'email' => true,
        'password' => true,
        'first_name' => true,
        'last_name' => true,
        'avatar' => true,
        'phone' => true,
        'date_of_birth' => true,
        'role' => true,
        'reset_token' => true,
        'token_expiry' => true,
        'created' => false,
        'modified' => false,
        // Associations
        'blog_articles' => true,
        'orders' => true,
        'user_preferences' => true,
    ];

    /**
     * Fields that are excluded from JSON versions of the entity.
     *
     * @var array<string>
     */
    protected array $_hidden = [
        'password',
    ];

    /**
     * Virtual fields
     * These can be accessed as $user->user_full_display and $user->full_name
     */
    protected array $_virtual = ['user_full_display', 'full_name'];

    /**
     * Get a readable display label for users (used as displayField)
     *
     * @return string
     */
    protected function _getUserFullDisplay(): string
    {
        $fullName = trim(($this->first_name ?? '') . ' ' . ($this->last_name ?? ''));
        return $fullName !== ''
            ? sprintf('%s (%s)', $fullName, $this->email)
            : (string)$this->email;
    }

    /**
     * Get full name for a user
     *
     * @return string
     */
    protected function _getFullName(): string
    {
        return trim(($this->first_name ?? '') . ' ' . ($this->last_name ?? ''));
    }

    /**
     * Automatically hash password before saving.
     *
     * @param string $password
     * @return string|null
     */
    protected function _setPassword(string $password): ?string
    {
        if (strlen($password) > 0) {
            return (new DefaultPasswordHasher())->hash($password);
        }

        return $password;
    }
}
