<?php

namespace apexl\Io\modules\file\entities;

use apexl\entityCore\enums\Casts;
use apexl\entityCore\traits\hasCasts;
use apexl\Io\includes\Entity;
use apexl\Io\modules\file\entities\operators\fileOperator;
use apexl\Io\modules\file\interfaces\HasFilesInterface;
use apexl\Io\services\FilePaths;
use DateTimeImmutable;
use function apexl\Io\container;

/**
 * @property int $id
 * @property string $name
 * @property string $path
 * @property string $mime
 * @property string $access_perm
 * @property DateTimeImmutable $created
 * @property int $created_by
 * @property DateTimeImmutable $modified
 * @property int $modified_by
 *
 * @property-read ?entityFile $entityFile
 *
 * @mixin fileOperator
 */
class fileEntity extends Entity
{
    public final const string TABLE = 'files';

    public final const string POST_STORE_WITH_RELATIONS_HOOK = 'postStoreWithRelations:files';
    private FilePaths $filePaths;

    use hasCasts;

    public function __construct()
    {
        parent::__construct(self::TABLE);
        $this->setOperator(new fileOperator(self::TABLE));
        $this->filePaths = container()->get(FilePaths::class);
    }

    public function casts(): array
    {
        return [
            'id' => Casts::INT,
            'created' => Casts::DATETIME_STAMP,
            'modified' => Casts::DATETIME_STAMP,
        ];
    }

    public function downloadFilePath(): string
    {
        return $this->path;
    }

    /**
     * function to get the full local file path of the file.
     * @return string
     */
    public function getLocalPath(): string
    {
        return $this->filePaths->webRoot($this->path);
    }

    public function delete($id = null): Entity
    {
        $path = $this->filePaths->webRoot($this->path);
        //unlink the attached file
        if (!file_exists($path)) {
            logger('error')->notice('Attempting to delete non-existent file at {path}', [
                'path' => $path,
            ]);
        } else {
            unlink($path);
        }

        return parent::delete($id);
    }

    public function definedRelations(): array
    {
        return [
            $this->hasOne('entityFile', entityFile::class, localKey: 'id', remoteKey: 'file_id'),
        ];
    }

    public function storeWithRelatedEntity(?HasFilesInterface $relatedEntity = null, ?string $fileKey = null): self
    {
        $this->store();

        if ($relatedEntity) {
            $fileKey = $fileKey ?: "upload_{$this->id}";
            $relatedEntity->addFile($fileKey, $this);
        }

        $this->hookManager->processHook(self::POST_STORE_WITH_RELATIONS_HOOK, $this);

        return $this;
    }

    public function getRelatedEntityClass(): ?string
    {
        return entityFile::findWhere('file_id', $this->id)->entity;
    }
}
