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

use League\Flysystem\Filesystem;
use Overtrue\Flysystem\Qiniu\QiniuAdapter;

class QiniuStorage implements StorageInterface
{
    protected Filesystem $filesystem;
    protected string $domain;

    public function __construct()
    {
        $cfg = (array)config('storage.qiniu', []);
        $accessKey = (string)($cfg['access_key'] ?? '');
        $secretKey = (string)($cfg['secret_key'] ?? '');
        $bucket = (string)($cfg['bucket'] ?? '');
        $this->domain = (string)($cfg['domain'] ?? '');

        if ($accessKey === '' || $secretKey === '' || $bucket === '' || $this->domain === '') {
            throw new \RuntimeException('Qiniu storage config is incomplete.');
        }

        $adapter = new QiniuAdapter($accessKey, $secretKey, $bucket, $this->domain);
        $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->domain, '/') . '/' . 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;
    }
}
