<?php

namespace Modules\Storage\Http\Controllers;

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use App\Api\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Modules\Storage\Models\Storage as StorageModel;

class OssController extends Controller
{

    /**
     * Notes   : 普通文件上传
     *
     * @Date   : 2021/4/25 5:25 下午
     * @Author : <Jason.C>
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    public function upload(Request $request)
    {
        $upload = $request->file('upload');

        $size = File::size($upload->path());

        if ($size > Config::get('storage.max_upload_size')) {
            return $this->failed('超过最大允许上传大小', 422);
        }
        $exists = true;
        $hash   = File::hash($upload->path());

        $existFile = StorageModel::where('driver', Config::get('storage.driver'))->where('hash', $hash)->first();

        if ($existFile) {
            $fullName = $existFile->path;
        } else {
            $path     = Config::get('storage.upload_path').date('/Y/m/d');
            $fileName = $hash.'.'.$upload->getClientOriginalExtension();
            $fullName = $path.'/'.$fileName;

            $uploaded = Storage::putFileAs($path, $upload, $fileName);

            if (! $uploaded) {
                return $this->failed('文件上传失败', 422);
            }
            $exists = false;
            StorageModel::create([
                'hash'   => $hash,
                'driver' => Config::get('storage.driver'),
                'type'   => $upload->getClientMimeType(),
                'size'   => $size,
                'path'   => $fullName,
            ]);
        }

        return $this->success([
            'exists' => $exists,
            'size'   => $size,
            'path'   => $fullName,
            'url'    => Storage::url($fullName),
        ]);
    }

    /**
     * Notes   : 多图片统一上传
     *
     * @Date   : 2021/8/23 13:49
     * @Author : Mr.wang
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    public function uploads(Request $request)
    {
        $fullFile = [];
        $files    = [];
        if ($request->file()) {
            $i = 1;
            foreach ($request->file() as $key => $upload) {
                $size = File::size($upload->path());

                if ($size > Config::get('storage.max_upload_size')) {
                    $message = '上传失败，图片大小超过5M';

                    return $this->failed($message, 422);
                }
                $hash = File::hash($upload->path());

                $existFile = StorageModel::where('driver', Config::get('storage.driver'))
                    ->where('hash', $hash)
                    ->first();
                if ($existFile) {
                    $fullName = $existFile->path;
                } else {
                    $path     = Config::get('storage.upload_path').date('/Y/m/d');
                    $fileName = $hash.'.'.$upload->getClientOriginalExtension();
                    $fullName = $path.'/'.$fileName;

                    $uploaded = Storage::putFileAs($path, $upload, $fileName);

                    if (! $uploaded) {
                        return $this->failed('文件上传失败', 422);
                    }
                    StorageModel::create([
                        'hash'   => $hash,
                        'driver' => Config::get('storage.driver'),
                        'type'   => $upload->getClientMimeType(),
                        'size'   => $size,
                        'path'   => $fullName,
                    ]);
                }
                $fullFile[] = Storage::url($fullName);
                $files[]    = $fullName;
                $i++;
            }

            return $this->success([
                'path' => $files,
                'url'  => $fullFile,
            ]);
        } else {
            return $this->failed('没有图片');
        }
    }

    /**
     * Notes   : STS 授权直传
     *
     * @Date   : 2021/4/25 5:24 下午
     * @Author : <Jason.C>
     * @return mixed
     */
    public function sts()
    {
        $config = Config::get('storage.disks.oss');

        try {
            AlibabaCloud::accessKeyClient(
                $config['access_key'],
                $config['secret_key'],
            )->regionId($config['RegionId'])->asDefaultClient();
        } catch (ClientException $e) {
            return $this->failed($e->getErrorMessage());
        }

        try {
            $Policy = [
                'Version'   => "1",
                'Statement' => [
                    [
                        'Effect'   => 'Allow',
                        'Action'   => 'oss:*',
                        'Resource' => [
                            "*",
                        ],
                    ],
                ],
            ];

            $result = AlibabaCloud::rpc()
                ->product('Sts')
                ->scheme('https') // https | http
                ->version('2015-04-01')
                ->action('AssumeRole')
                ->method('POST')
                ->host('sts.aliyuncs.com')
                ->options([
                    'query' => [
                        'RegionId'        => $config['RegionId'],
                        'RoleArn'         => $config['RoleArn'],
                        'RoleSessionName' => 'RoleSessionName',
                        // 'Policy'          => json_encode($Policy),
                        'DurationSeconds' => 3600,
                    ],
                ])
                ->request();

            return $this->success([
                'secure'          => true,
                'bucket'          => $config['bucket'],
                'region'          => $config['RegionId'], // 前缀带 oss- ？
                'accessKeyId'     => $result->Credentials->AccessKeyId,
                'accessKeySecret' => $result->Credentials->AccessKeySecret,
                'stsToken'        => $result->Credentials->SecurityToken,
                'endpoint'        => $config['endpoint'],
                'cname'           => $config['isCName'],
            ]);
        } catch (ClientException | ServerException $e) {
            return $this->failed($e->getErrorMessage());
        }
    }

}
