<?php

declare(strict_types=1);

namespace apexl\Io\dto\Relationship;

use apexl\entityCore\collections\EntityCollection;
use apexl\Io\includes\Entity;
use apexl\Io\interfaces\QueryDecorator;
use apexl\Io\interfaces\RelationOrderBy;
use apexl\Io\interfaces\RelationshipInterface;
use apexl\Io\interfaces\RelationSqlFragment;

final readonly class HasOne extends OneToOne
{
    /** @param class-string<Entity> $remoteEntity */
    public static function create(
        string $name,
        Entity $localEntity,
        string $remoteEntity,
        ?string $localKey = null,
        ?string $remoteKey = null,
        ?string $aliasedRemoteTable = null,
        ?RelationshipInterface $parent = null,
        ?QueryDecorator $queryCallback = null,
        ?RelationSqlFragment $rawJoin = null,
        ?QueryDecorator $rawQuery = null,
        ?RelationOrderBy $orderByCallback = null,
    ): self {
        return new self(
            name: $name,
            localEntity: $localEntity,
            remoteEntity: $remoteEntity,
            localTable: $localEntity->getTableName(),
            localKey: $localKey ?? sprintf('%s_id', $name),
            remoteKey: $remoteKey,
            parent: $parent,
            aliasedRemoteTable: $aliasedRemoteTable,
            queryCallback: $queryCallback,
            rawJoin: $rawJoin,
            rawQuery: $rawQuery,
            orderByCallback: $orderByCallback,
        );
    }

    public function set(int|array|EntityCollection|Entity $entity): void
    {
        $this->assertSetType($entity);

        $id = $this->ensureEntityId($entity);
        $entity = $this->ensureEntity($entity);
        $this->assertEntityType($entity);

        $this->localEntity->{$this->getName()} = $entity;

        $this->localEntity->{$this->getLocalKey()} = $id;

        $this->localEntity->store();
    }

    public function clear(): void
    {
        $this->localEntity->{$this->localKey} = null;
        $this->localEntity->store();
    }
}


