<?php

namespace App\Services;

use App\Models\SystemConfig;
use FFMpeg;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use OSS\OssClient;
use PHPUnit\Util\Exception;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use App\Services\Base\ErrorCode;
use App\Models\BaseAttachment;

class AttachmentServer
{

    public function __construct()
    {
        //在 .env 文件里配置下面可测试文件上传OSS
        //ALI_OSS_ACCESS_ID=LTAI5tHMYxyoEkmGqQZjbpmk
        //ALI_OSS_ACCESS_KEY=Fqj8J1JH0yyRpLvOjNFj5usjvfvHns
        //ALI_OSS_BUCKET=zhengda
        //ALI_OSS_ENDPOINT=oss-cn-chengdu.aliyuncs.com

        $this->fileDriver = env('FILESYSTEM_DRIVER');
        $this->bucket = env('ALI_OSS_BUCKET');
        $this->accessId = env('ALI_OSS_ACCESS_ID');
        $this->accessKey = env('ALI_OSS_ACCESS_KEY');
        $this->endPoint = env('ALI_OSS_ENDPOINT');
        $this->ossClient = new OssClient($this->accessId, $this->accessKey, $this->endPoint);
    }

    /**
     * @param Request $request
     * @param $key
     * @param string $tag
     * @param float|int $size
     * @param array $mimeType
     * @return array|mixed
     * @throws \Exception
     */
    public function uploadAttachment(Request $request, $key, $tag = 'files', $size = 200 * 1024 * 1024, array $mimeType = [])
    {
        if ($request->hasFile($key)) {
            $files = $request->file($key);
            if ($files === null) {
                throw new \Exception(trans('api.ATTACHMENT_FILE_NULL'));
            }
            if ($files instanceof UploadedFile) {
                $files = [$files];
            }
            $result = [];
            foreach ($files as $idx => $file) {
                if (!$file->isValid()) {
                    throw new \Exception(trans('api.ATTACHMENT_TYPE_ERROR'));
                    continue;
                }
                $fileSize = $file->getSize();
                if ($fileSize > $size) {
                    throw new \Exception(trans('api.ATTACHMENT_SIZE_EXCEEDED'));
                    continue;
                }
                $fileMimeType = $file->getMimeType();
                if (!empty($mimeType) && !in_array($fileMimeType, $mimeType)) {
                    throw new \Exception(trans('api.ATTACHMENT_TYPE_ERROR'));
                    continue;
                }
                $clientName = $file->getClientOriginalName();
                $md5 = md5($clientName . time());
                $md5_filename = $md5 . '.' . $file->getClientOriginalExtension();
                try {
                    //本地上传
                    if (env('FILESYSTEM_DRIVER') == 'local') {
                        $rel_path = '/upload/' . $tag . '/' . date('Ymd');
                        $path = public_path() . $rel_path;
                        if (!file_exists($path)) {
                            if (!@mkdir($path, 0755, true)) {
                                throw new \Exception(trans('api.ATTACHMENT_MAKE_FOLDER_ERROR'));
                            }
                        }
                        $file->move($path, $md5_filename);
                        $realPath = $path . '/' . $md5_filename;
                        $urlPath = $rel_path . '/' . $md5_filename;
                        if ($fileMimeType == "video/mp4" || $fileMimeType == "video/quicktime") {
                            $ffmpeg = FFMpeg\FFMpeg::create(array(
                                'ffmpeg.binaries' => '/usr/bin/ffmpeg',
                                'ffprobe.binaries' => '/usr/bin/ffprobe'
                            ));
                            $video = $ffmpeg->open($realPath);
                            $vpath = public_path() . '/upload/vpic/';
                            if (!file_exists($vpath)) {
                                if (!@mkdir($vpath, 0755, true)) {
                                    return trans('api.ATTACHMENT_MAKE_FOLDER_ERROR');
                                }
                            }
                            $pic = $vpath . $md5 . '.jpg';
                            $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(1))->save($pic);
                        }
                        $result[$idx] = 'http://' . $_SERVER['HTTP_HOST'] . $urlPath;

                    } elseif (env('FILESYSTEM_DRIVER') == 'oss') {

                        $tmppath  = $file->getRealPath(); //获取上传图片的临时地址
                        $fileName = date('YmdHis') .rand(10000, 99999). '.' . $file->getClientOriginalExtension(); //生成文件名
                        $pathName = $tag . '/' . date('Y-m') . '/' . $fileName;
                        $upResult = $this->ossClient->uploadFile($this->bucket, $pathName, $tmppath, ['ContentType' => $file->getClientMimeType()]); //上传图片到阿里云OSS
                        $url = $upResult['info']['url'];
                        $realPath = $url;
                        $urlPath  = $url;
                        $result[$idx] = $url;
                    }
                    //将上传的图片存入到数据表作为记录
                    $attachment = new BaseAttachment();
                    $attachment->name = $clientName;
                    $attachment->md5  = $md5;
                    $attachment->path = $realPath;
                    $attachment->url  = $urlPath;
                    $attachment->size = $fileSize;
                    $attachment->file_type = $fileMimeType;
                    if (!$attachment->save()) {
                        @unlink($realPath);
                        throw new \Exception(trans('api.ATTACHMENT_SAVE_ERROR'));
                    }
                } catch (FileException $e) {
                    throw new \Exception(trans('api.ATTACHMENT_UPLOAD_INVALID'));
                }
            }
            if (count($result) == 1) {
                return array_shift($result);
            }
            return $result;
        } else {
            throw new \Exception(trans('api.ATTACHMENT_UPLOAD_INVALID'));
        }
    }

    /**
     * 删除附件
     *
     * @param $picUrl 图片地址
     * @return int 错误码or 0（成功）
     */
    public function deleteAttachment($picUrl)
    {
        if ($this->fileDriver == 'local') {
            $attachment = BaseAttachment::where(['path' => $picUrl])->first();
            if (!$attachment) {
                return false;
            }
            if (file_exists($attachment->path)) {
                if (@unlink($attachment->path)) {
                    if (!$attachment->delete()) {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } elseif ($this->fileDriver == 'oss') {
            $this->ossClient->deleteObject($this->bucket, $picUrl);
        }

        return true;
    }

}
