<?php

namespace Lean\Api\Form;

use CSSLSJ\ExamenFga\Api\{Form\Location\SessionContext, Lib, Entity};
use Picea\Ui\Method\{ FormContextInterface, Message\ErrorMessage };

use Ulmus\Attribute\Property\Field;
use Lean\Api\Attribute\EntityField;
use Lean\LanguageHandler;
use Psr\Http\Message\ServerRequestInterface;

use Ulmus\Entity\EntityInterface;
use Ulmus\Entity\Field\Datetime;
use function CSSLSJ\ExamenFga\Api\View\{ lang };

abstract class Save implements \Picea\Ui\Method\FormInterface {

    public function __construct(
        protected LanguageHandler $languageHandler,
#        public EntityInterface $entity,
    ) {}

    public function getEntity() : EntityInterface
    {
        if (! isset($this->entity)) {
            throw new \InvalidArgumentException($this->lang("lean.api.form.save.error.entity"));
        }

        return $this->entity;
    }

    public function validate(FormContextInterface $context) : bool
    {
        # Context is validating inputs
        return $context->valid($this->getEntity()->isLoaded() ? $this->getEntity() : null);
    }

    public function execute(FormContextInterface $context) : void
    {
        $entity = $this->getEntity();

        if  ($entity->isLoaded() ) {
            $entity->updatedAt = new Datetime();
        }
        else {
            $entity->createdAt = new Datetime();
        }

        try {
            $this->assignContextToEntity($context);

            if ( $entity::repository()->save($entity) ) {
                $context->pushMessage(Lib\Message::generateSuccess(
                    $this->lang('lean.api.form.save.success.entity')
                ));
            }
            else {
                throw new \InvalidArgumentException($this->lang('lean.api.form.save.error.entity'));
            }
        }
        catch(\Throwable $ex) {
            throw new \ErrorException($this->lang('lean.api.form.save.error.pdo', [ 'error' => $ex->getMessage() ]));
        }
    }

    protected function lang(string $key, array $variables = [])
    {
        return $this->languageHandler->languageFromKey($key, $variables);
    }

    protected function assignContextToEntity(FormContextInterface $context) : void
    {
        $entity = $this->getEntity();

        foreach($entity::resolveEntity()->fieldList() as $key => $property) {
            $field = $property->getAttribute(Field::class)->object;

            if (! $field->readonly) {
                $apiField = $property->getAttribute(EntityField::class)->object ?? null;

                if ($apiField) {
                    if ($apiField->field) {
                        if ( isset($context->{$apiField->field}) ) {
                            $entity->$key = $context->{$apiField->field};
                        }
                    }
                    else {
                        if ( isset($context->{$key}) ) {
                            $entity->$key = $context->{$key};
                        }
                    }
                }
            }
        }
    }
}