<?php

namespace Kylin\Storage\Adapters;

use Kylin\Storage\Contracts\StorageAdapterInterface;
use Kylin\Storage\Aliyun\OssClient;
use Kylin\Storage\Aliyun\Core\OssException;

class AliyunAdapter implements StorageAdapterInterface
{
    private OssClient $client;
    private string $bucket;
    private string $endpoint;

    public function __construct(array $config)
    {
        $this->bucket = $config['bucket'];
        $this->endpoint = $config['endpoint'];

        try {
            $this->client = new OssClient(
                $config['access_key'],
                $config['access_secret'],
                $config['endpoint'],
                $config['cname'] ?? false,
                $config['security_token'] ?? null,
                $config['request_proxy'] ?? null
            );
        } catch (OssException $e) {
            throw new \RuntimeException("Aliyun OSS client init failed: {$e->getMessage()}");
        }
    }

    public function upload(string $localPath, string $remotePath, array $options = []): string
    {
        $this->client->uploadFile($this->bucket, $remotePath, $localPath, $options);
        return $remotePath;
    }

    public function download(string $remotePath, ?string $localPath = null): string
    {
        $content = $this->client->getObject($this->bucket, $remotePath);

        if ($localPath) {
            file_put_contents($localPath, $content);
            return $localPath;
        }

        $tmpPath = tempnam(sys_get_temp_dir(), 'oss_');
        file_put_contents($tmpPath, $content);
        return $tmpPath;
    }

    public function delete(string $remotePath): bool
    {
        $this->client->deleteObject($this->bucket, $remotePath);
        return true;
    }

    public function getUrl(string $remotePath): string
    {
        $protocol = parse_url($this->endpoint, PHP_URL_SCHEME) ?: 'https';
        $host = parse_url($this->endpoint, PHP_URL_HOST) ?: $this->endpoint;
        return "{$protocol}://{$this->bucket}.{$host}/{$remotePath}";
    }

    public function getSignedUrl(string $remotePath, int $expires = 3600): string
    {
        return $this->client->signUrl($this->bucket, $remotePath, $expires);
    }

    public function exists(string $remotePath): bool
    {
        try {
            $this->client->getObjectMeta($this->bucket, $remotePath);
            return true;
        } catch (OssException) {
            return false;
        }
    }

    public function getSize(string $remotePath): int
    {
        try {
            $meta = $this->client->getObjectMeta($this->bucket, $remotePath);
            return (int) ($meta['content-length'] ?? 0);
        } catch (OssException) {
            return 0;
        }
    }

    public function getMimeType(string $remotePath): string
    {
        try {
            $meta = $this->client->getObjectMeta($this->bucket, $remotePath);
            return $meta['content-type'] ?? 'application/octet-stream';
        } catch (OssException) {
            return 'application/octet-stream';
        }
    }
}
