<?php

declare(strict_types=1);

namespace Drupal\miniorange_webauthn\Entity;

use Drupal;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\user\Entity\User;
use ParagonIE\ConstantTime\Base64UrlSafe;

/**
 * Defines the miniorange webauthn credential entity class.
 *
 * @ContentEntityType(
 *   id = "mo_webauthn_credential",
 *   label = @Translation("miniOrange Webauthn Credential"),
 *   label_collection = @Translation("miniOrange Webauthn Credentials"),
 *   label_singular = @Translation("miniorange webauthn credential"),
 *   label_plural = @Translation("miniorange webauthn credentials"),
 *   label_count = @PluralTranslation(
 *     singular = "@count miniorange webauthn credentials",
 *     plural = "@count miniorange webauthn credentials",
 *   ),
 *   handlers = {
 *     "list_builder" = "Drupal\miniorange_webauthn\MoWebauthnCredentialListBuilder",
 *   },
 *   base_table = "mo_webauthn_credential",
 *   links = {
 *      "collection" = "/user/{user}/mo-webauthn",
 *   },
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "uuid" = "uuid",
 *   },
 * )
 */
final class MoWebauthnCredential extends ContentEntityBase implements ContentEntityInterface
{

    use EntityChangedTrait;

    public const ENTITY_ID = 'mo_webauthn_credential';

    public const UID = 'uid';
    public const CREDENTIAL_ID = 'credential_id';
    private const LABEL = 'label';
    private const CREDENTIAL = 'credential';


    /**
     * {@inheritdoc}
     */
    public static function baseFieldDefinitions(EntityTypeInterface $entity_type): array
    {

        $fields = parent::baseFieldDefinitions($entity_type);

        $fields[self::LABEL] = BaseFieldDefinition::create('string')
            ->setLabel(t('WebAuthn credential label'))
            ->setDescription(t('The WebAuthn credential label.'))
            ->setRequired(TRUE)
            ->setSetting('max_length', 255)
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields[self::UID] = BaseFieldDefinition::create('entity_reference')
            ->setLabel(t('Authored by'))
            ->setDescription(t('The user ID of the WebAuthn author.'))
            ->setRequired(TRUE)
            ->setSetting('target_type', 'user')
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields[self::CREDENTIAL_ID] = BaseFieldDefinition::create('string')
            ->setLabel(t('WebAuthn credential ID'))
            ->setDescription(t('The credential ID of the WebAuthn.'))
            ->setRequired(TRUE)
            ->setSetting('max_length', 255)
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields[self::CREDENTIAL] = BaseFieldDefinition::create('string_long')
            ->setLabel(t('WebAuthn credential.'))
            ->setDescription(t('The credential of the WebAuthn.'))
            ->setRequired(TRUE)
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields['status'] = BaseFieldDefinition::create('boolean')
            ->setLabel(t('WebAuthn status'))
            ->setDescription(t('Whether the WebAuthn is active or blocked.'))
            ->setDefaultValue(TRUE)
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields['created'] = BaseFieldDefinition::create('created')
            ->setLabel(t('Created'))
            ->setDescription(t('The time that the WebAuthn was created.'))
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        $fields['changed'] = BaseFieldDefinition::create('changed')
            ->setLabel(t('Changed'))
            ->setDescription(t('The time that the WebAuthn was last edited.'))
            ->setTranslatable(FALSE)
            ->setRevisionable(FALSE);

        return $fields;
    }

    public function getLabel(): string
    {
        return $this->get(self::LABEL)->getString();
    }

    public function setLabel($label)
    {
        $this->set(self::LABEL, $label);
    }

    public function getUid(): string
    {
        return $this->get(self::UID)->getString();
    }

    public function setUid(User $uid)
    {
        $this->set(self::UID, $uid);
    }

    public function getUserEntity()
    {
        return User::load(Base64UrlSafe::decode($this->get(self::UID)));
    }

    public function getCredentialId(): string
    {
        return $this->get(self::CREDENTIAL_ID)->getString();
    }

    public function setCredentialId($credential_id)
    {
        $this->set(self::CREDENTIAL_ID, $credential_id);
    }

    public function getCredential(): string
    {
        return $this->get(self::CREDENTIAL)->getString();
    }

    public function setCredential($credential)
    {
        $this->set(self::CREDENTIAL, $credential);
    }

    public function getCreatedTime()
    {
        return $this->get('created')->value;
    }

    public static function findBy(array $conditions): array
    {
        try {
            return Drupal::entityTypeManager()
                ->getStorage(self::ENTITY_ID)
                ->loadByProperties($conditions);
        } catch (\Exception $e) {
            return [];
        }
    }

    public static function findOneBy(array $conditions): ?self
    {
        return current(self::findBy($conditions)) ?: NULL;
    }
}

