<?php
namespace app\common\service\storage;

use League\Flysystem\Filesystem;
use League\Flysystem\Adapter\Local;

class LocalStorage implements StorageInterface
{
    protected Filesystem $filesystem;
    protected string $rootPath;
    protected string $urlPrefix;

    public function __construct(?string $rootPath = null, ?string $urlPrefix = null)
    {
        $this->rootPath = $rootPath ?: app()->getRootPath() . 'public/storage';
        $this->urlPrefix = $urlPrefix ?: '/storage';

        if (!is_dir($this->rootPath)) {
            @mkdir($this->rootPath, 0775, true);
        }

        $adapter = new Local($this->rootPath);
        $this->filesystem = new Filesystem($adapter);
    }

    public function put($file, string $keyPrefix = ''): array
    {
        $key = $this->buildKey($file, $keyPrefix);
        $path = $file->getPathname();
        $stream = fopen($path, 'r');
        if ($stream === false) {
            throw new \RuntimeException('Unable to open upload stream.');
        }

        try {
            $this->filesystem->writeStream($key, $stream);
        } catch (\Throwable $e) {
            throw new \RuntimeException('Upload failed: ' . $e->getMessage());
        } finally {
            if (is_resource($stream)) {
                fclose($stream);
            }
        }

        return ['key' => $key, 'url' => $this->url($key)];
    }

    public function delete(string $key): void
    {
        try {
            if ($this->filesystem->has($key)) {
                $this->filesystem->delete($key);
            }
        } catch (\Throwable $e) {
            // Ignore physical delete failures.
        }
    }

    public function url(string $key): string
    {
        return rtrim($this->urlPrefix, '/') . '/' . ltrim($key, '/');
    }

    public function exists(string $key): bool
    {
        return $this->filesystem->has($key);
    }

    protected function buildKey($file, string $keyPrefix = ''): string
    {
        $originName = method_exists($file, 'getOriginalName') ? (string)$file->getOriginalName() : '';
        $ext = strtolower(pathinfo($originName, PATHINFO_EXTENSION));
        $prefix = trim($keyPrefix ?: 'material', '/');
        $key = $prefix . '/' . date('Ymd') . '/' . uniqid('', true);
        return $ext ? ($key . '.' . $ext) : $key;
    }
}
