<?php 
namespace model;

use AlibabaCloud\Oss\V2 as Oss;

class alioss
{       
    public $client = null;
    private $bucket = null;
    
    public function __construct($bucket = null,$openVersion = true)
    {   
        $osscfg = \mvc::$cfg['OSS'];
        if($osscfg && !$this->client)
        {
            $region = $osscfg['region'];
            $this->bucket = $bucket ?: $osscfg['bucket']; // 如果未指定bucket，则使用配置中的默认bucket

            $credentialsProvider = new Oss\Credentials\StaticCredentialsProvider(
                $osscfg['AccessKeyId'],
                $osscfg['AccessKeySecret']
            );

            // 使用SDK的默认配置
            $cfg = Oss\Config::loadDefault();
            $cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者
            $cfg->setRegion($region); // 设置Bucket所在的地域

            // 创建OSS客户端实例
            $this->client = new Oss\Client($cfg);
        }

        // if($openVersion && !$closeInit){
        //     $result = $this->getBucketVersioning();
        //     if($result['status']!='Enabled'){
        //         $this->enableBucketVersioning();
        //     }
        // }
    }

    /**
     * 上传文件到OSS
     * @param string $objectName 对象名称（OSS上的文件路径）
     * @param string $filePath 本地文件路径
     * @param array $options 上传选项
     * @return bool
     */
    public function putObject($objectName, $filePath, $options = [])
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }

        // 使用fopen以只读模式打开文件，并通过Utils::streamFor将文件内容转换为流
        $body = Oss\Utils::streamFor(fopen($filePath, 'r'));

        // 创建PutObjectRequest对象，用于上传文件
        $request = new Oss\Models\PutObjectRequest($this->bucket,$objectName,'public-read');
        $request->body = $body;
        try {
            $result = $this->client->putObject($request);
            
            return $result;
        } catch (\Exception $e) {
            error_log('OSS上传失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 上传文件到OSS（版本控制模式）
     * @param string $objectName 对象名称（OSS上的文件路径）
     * @param string $filePath 本地文件路径
     * @param array $options 上传选项
     * @return mixed 上传结果，包含版本ID（如果启用了版本控制）
     */
    public function putObjectWithVersioning($objectName, $filePath, $options = [])
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }

        // 使用fopen以只读模式打开文件，并通过Utils::streamFor将文件内容转换为流
        $body = Oss\Utils::streamFor(fopen($filePath, 'r'));

        // 创建PutObjectRequest对象，用于上传文件
        $request = new Oss\Models\PutObjectRequest($this->bucket,$objectName,'public-read');
        $request->body = $body;
        try {
            $result = $this->client->putObject($request);
            
            // 检查是否启用了版本控制并获取版本ID
            $versionId = null;
            if (isset($result->versionId)) {
                $versionId = $result->versionId;
            } elseif (isset($result->headers['x-oss-version-id'])) {
                $versionId = $result->headers['x-oss-version-id'][0];
            }
            
            return [
                'success' => true,
                'versionId' => $versionId,
                'result' => $result
            ];
        } catch (\Exception $e) {
            error_log('OSS上传失败: ' . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }


    /**
     * 下载文件到本地
     * @param string $objectName OSS对象名称
     * @param string $localPath 本地保存路径
     * @param string|null $versionId 版本ID（可选）
     * @return bool
     */
    public function getObject($objectName, $localPath, $versionId = null)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            // 创建GetObjectRequest对象，用于获取指定对象的内容
            $request = new Oss\Models\GetObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }

            // 执行获取对象操作
            $result = $this->client->getObject($request);

            // 将内容写入本地文件
            file_put_contents($localPath, $result->body->getContents());
            return true;
        } catch (\Exception $e) {
            error_log('OSS下载失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取OSS文件内容
     * @param string $objectName OSS对象名称
     * @param string|null $versionId 版本ID（可选）
     * @return string|bool 成功返回文件内容，失败返回false
     */
    public function getObjectContent($objectName, $versionId = null)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            // 创建GetObjectRequest对象，用于获取指定对象的内容
            $request = new Oss\Models\GetObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }

            // 执行获取对象操作
            $result = $this->client->getObject($request);

            return $result->body->getContents();
        } catch (\Exception $e) {
            error_log('OSS获取内容失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 删除OSS上的文件
     * @param string $objectName 对象名称
     * @param string|null $versionId 版本ID（可选，如果不指定则删除最新版本）
     * @return bool
     */
    public function deleteObject($objectName, $versionId = null)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            // 创建DeleteObjectRequest对象，用于删除指定的对象
            $request = new Oss\Models\DeleteObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }

            // 执行删除对象操作
            $result = $this->client->deleteObject($request);
                    
            return $result;
        } catch (\Exception $e) {
            error_log('OSS删除失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 列出OSS上的文件
     * @param array $options 列表选项
     * @return array
     */
    public function listObjects($options = [])
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\ListObjectsRequest($this->bucket);
            
            $result = $this->client->listObjects($request);
            
            return [
                'success' => true,
                'objects' => $result->contents ?? [],
                'common_prefixes' => $result->commonPrefixes ?? []
            ];
        } catch (\Exception $e) {
            error_log('OSS列出文件失败: ' . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * 列出OSS上对象的所有版本
     * @param array $options 列表选项
     * @return array
     */
    public function listObjectVersions()
    {
        if (!$this->client) {
            throw new Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\ListObjectVersionsRequest($this->bucket);
            
            $result = $this->client->listObjectVersions($request);
            
            return [
                'success' => true,
                'versions' => $result->versions ?? [],
                'delete_markers' => $result->deleteMarkers ?? [],
                'common_prefixes' => $result->commonPrefixes ?? []
            ];
        } catch (Exception $e) {
            error_log('OSS列出对象版本失败: ' . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * 检查文件是否存在
     * @param string $objectName 对象名称
     * @param string|null $versionId 版本ID（可选）
     * @return bool
     */
    public function doesObjectExist($objectName, $versionId = null)
    {
        if (!$this->client) {
            throw new Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\HeadObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }
            
            $result = $this->client->headObject($request);
            
            return $result !== null;
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * 获取文件信息
     * @param string $objectName 对象名称
     * @param string|null $versionId 版本ID（可选）
     * @return array|bool 成功返回文件信息，失败返回false
     */
    public function getObjectInfo($objectName, $versionId = null)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\HeadObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }
            
            $result = $this->client->headObject($request);
            
            // 根据实际返回结果调整字段访问方式
            return [
                'size' => $result->contentLength ?? 0,
                'last_modified' => $result->lastModified ?? null,
                'etag' => $result->eTag ?? null,
                'content_type' => $result->contentType ?? null,
                'version_id' => $result->versionId ?? null,
                'storage_class' => $result->storageClass ?? null,
            ];
        } catch (\Exception $e) {
            error_log('OSS获取文件信息失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 生成签名URL用于临时访问
     * @param string $objectName 对象名称
     * @param int $expires 过期时间（秒）
     * @param string|null $versionId 版本ID（可选）
     * @return string
     */
    public function getSignedUrl($objectName, $expires = 3600, $versionId = null)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            // 创建GetObjectRequest对象
            $request = new Oss\Models\GetObjectRequest($this->bucket,$objectName);
            
            if ($versionId) {
                $request->versionId = $versionId;
            }
            
            // 使用正确的日期间隔格式
            $args = [
                'expires' => new \DateInterval('PT' . $expires . 'S')
            ];
            
            $presignedResult = $this->client->presign($request, $args);
            
            return $presignedResult->url;
        } catch (\Exception $e) {
            error_log('OSS生成签名URL失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 检查存储桶是否启用了版本控制
     * @return array
     */
    public function getBucketVersioning()
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\GetBucketVersioningRequest($this->bucket);

            $result = $this->client->getBucketVersioning($request);
            
            return [
                'success' => true,
                'status' => $result->status ?? null,
                'mfa_delete' => $result->mfaDelete ?? null,
                'raw_result' => $result
            ];
        } catch (\Exception $e) {
            error_log('OSS获取版本控制状态失败: ' . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * 启用存储桶版本控制
     * @return bool
     */
    public function enableBucketVersioning()
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            $versioningConfiguration = new Oss\Models\VersioningConfiguration('Enabled');
            $request = new Oss\Models\PutBucketVersioningRequest($this->bucket,$versioningConfiguration);

            $result = $this->client->putBucketVersioning($request);
            
            return true;
        } catch (\Exception $e) {
            error_log('OSS启用版本控制失败: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取对象的ACL
     * @param string $objectName 对象名称
     * @return array
     */
    public function getObjectAcl($objectName)
    {
        if (!$this->client) {
            throw new \Exception('OSS客户端未初始化');
        }
        
        try {
            $request = new Oss\Models\GetObjectAclRequest($this->bucket,$objectName);

            $result = $this->client->getObjectAcl($request);
            
            return [
                'success' => true,
                'grants' => $result->grants ?? [],
                'owner' => $result->owner ?? null,
                'raw_result' => $result
            ];
        } catch (\Exception $e) {
            error_log('OSS获取对象ACL失败: ' . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * 获取公开访问URL
     * @param string $objectName 对象名称
     * @return string
     */
    public static function getPublicUrl($objectName)
    {
        $osscfg = \mvc::$cfg['OSS'];
        
        if (isset($osscfg['url']) && $osscfg['url']) {
            // 如果配置了自定义域名
            return rtrim($osscfg['url'], '/') . '/' . ltrim($objectName, '/');
        } else {
            // 使用默认的OSS访问地址
            $endpoint = $osscfg['endpoint'] ?? $osscfg['region'] . '.aliyuncs.com';
            return 'https://' . $osscfg['bucket'] . '.' . $endpoint . '/' . $objectName;
        }
    }

    /**
     * 获取当前使用的bucket
     * @return string
     */
    public function getBucket()
    {
        return $this->bucket;
    }
}