<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台（PHP版）
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码，建议反馈是我们前进的动力
// | 开源版本可自由商用，可去除界面版权logo
// | gitee下载：https://gitee.com/likeshop_gitee/likeadmin
// | github下载：https://github.com/likeshop-github/likeadmin
// | 访问官网：https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------

namespace app\common\service;


use app\common\enum\FileEnum;
use app\common\model\file\File;
use app\common\service\storage\Driver as StorageDriver;
use Exception;


class UploadService
{

    /**
     * @notes 上传图片
     * @param $cid
     * @param int $user_id
     * @param string $saveDir
     * @return array
     * @throws Exception
     * @author 段誉
     * @date 2021/12/29 16:30
     */
    public static function image($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/images')
    {
        try {
            $config = [
                'default' => ConfigService::get('storage', 'default', 'local'),
                'engine'  => ConfigService::get('storage') ?? ['local'=>[]],
            ];

            // 2、执行文件上传
            $StorageDriver = new StorageDriver($config);
            $StorageDriver->setUploadFile('file');
            $fileName = $StorageDriver->getFileName();
            $fileInfo = $StorageDriver->getFileInfo();

            // 校验上传文件后缀
            if (!in_array(strtolower($fileInfo['ext']), config('project.file_image'))) {
                throw new Exception("上传图片不允许上传". $fileInfo['ext'] . "文件");
            }

            // 上传文件
            $saveDir = self::getUploadUrl($saveDir);
            if (!$StorageDriver->upload($saveDir)) {
                throw new Exception($StorageDriver->getError());
            }

            // 3、处理文件名称
            if (strlen($fileInfo['name']) > 128) {
                $name = substr($fileInfo['name'], 0, 123);
                $nameEnd = substr($fileInfo['name'], strlen($fileInfo['name'])-5, strlen($fileInfo['name']));
                $fileInfo['name'] = $name . $nameEnd;
            }

            // 4、写入数据库中
            $file = File::create([
                'cid'         => $cid,
                'type'        => FileEnum::IMAGE_TYPE,
                'name'        => $fileInfo['name'],
                'uri'         => $saveDir . '/' . str_replace("\\","/", $fileName),
                'source'      => $source,
                'source_id'   => $sourceId,
                'create_time' => time(),
            ]);

            // 5、返回结果
            return [
                'id'   => $file['id'],
                'cid'  => $file['cid'],
                'type' => $file['type'],
                'name' => $file['name'],
                'uri'  => FileService::getFileUrl($file['uri']),
                'url'  => $file['uri']
            ];

        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }


    /**
     * @notes 视频上传
     * @param $cid
     * @param int $user_id
     * @param string $saveDir
     * @return array
     * @throws Exception
     * @author 段誉
     * @date 2021/12/29 16:32
     */
    public static function video($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/video')
    {
        try {
            $config = [
                'default' => ConfigService::get('storage', 'default', 'local'),
                'engine'  => ConfigService::get('storage') ?? ['local'=>[]],
            ];

            // 2、执行文件上传
            $StorageDriver = new StorageDriver($config);
            $StorageDriver->setUploadFile('file');
            $fileName = $StorageDriver->getFileName();
            $fileInfo = $StorageDriver->getFileInfo();

            // 校验上传文件后缀
            if (!in_array(strtolower($fileInfo['ext']), config('project.file_video'))) {
                throw new Exception("上传视频不允许上传". $fileInfo['ext'] . "文件");
            }

            // 上传文件
            $saveDir = self::getUploadUrl($saveDir);
            if (!$StorageDriver->upload($saveDir)) {
                throw new Exception($StorageDriver->getError());
            }

            // 3、处理文件名称
            if (strlen($fileInfo['name']) > 128) {
                $name = substr($fileInfo['name'], 0, 123);
                $nameEnd = substr($fileInfo['name'], strlen($fileInfo['name'])-5, strlen($fileInfo['name']));
                $fileInfo['name'] = $name . $nameEnd;
            }

            // 4、写入数据库中
            $file = File::create([
                'cid'         => $cid,
                'type'        => FileEnum::VIDEO_TYPE,
                'name'        => $fileInfo['name'],
                'uri'         => $saveDir . '/' . str_replace("\\","/", $fileName),
                'source'      => $source,
                'source_id'   => $sourceId,
                'create_time' => time(),
            ]);

            // 5、返回结果
            return [
                'id'   => $file['id'],
                'cid'  => $file['cid'],
                'type' => $file['type'],
                'name' => $file['name'],
                'uri'  => FileService::getFileUrl($file['uri']),
                'url'  => $file['uri']
            ];

        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * @notes 上传文件
     * @param $cid
     * @param int $sourceId
     * @param int $source
     * @param string $saveDir
     * @return array
     * @throws Exception
     * @author dw
     * @date 2023/06/26
     */
    public static function file($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/file')
    {
        try {
            $config = [
                'default' => ConfigService::get('storage', 'default', 'local'),
                'engine'  => ConfigService::get('storage') ?? [ 'local' => [] ],
            ];

            // 2、执行文件上传
            $StorageDriver = new StorageDriver($config);
            $StorageDriver->setUploadFile('file');
            $fileName = $StorageDriver->getFileName();
            $fileInfo = $StorageDriver->getFileInfo();

            // 校验上传文件后缀
            if (!in_array(strtolower($fileInfo['ext']), config('project.file_file'))) {
                throw new Exception("上传文件不允许上传" . $fileInfo['ext'] . "文件");
            }

            // 上传文件
            $saveDir = self::getUploadUrl($saveDir);
            if (!$StorageDriver->upload($saveDir)) {
                throw new Exception($StorageDriver->getError());
            }

            // 3、处理文件名称
            if (strlen($fileInfo['name']) > 128) {
                $name = substr($fileInfo['name'], 0, 123);
                $nameEnd = substr($fileInfo['name'], strlen($fileInfo['name']) - 5, strlen($fileInfo['name']));
                $fileInfo['name'] = $name . $nameEnd;
            }

            // 4、写入数据库中
            $file = File::create([
                'cid'         => $cid,
                'type'        => FileEnum::FILE_TYPE,
                'name'        => $fileInfo['name'],
                'uri'         => $saveDir . '/' . str_replace("\\", "/", $fileName),
                'source'      => $source,
                'source_id'   => $sourceId,
                'create_time' => time(),
            ]);

            // 5、返回结果
            return [
                'id'   => $file['id'],
                'cid'  => $file['cid'],
                'type' => $file['type'],
                'name' => $file['name'],
                'uri'  => FileService::getFileUrl($file['uri']),
                'url'  => $file['uri']
            ];

        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    public static function base64Image($cid, $base64_image, string $saveDir = 'uploads/signs')
    {
        try {
            // 提取Base64数据，去掉"data:image/png;base64,"前缀
            $base64_image_content = explode(',', $base64_image)[1];
            // 解码Base64数据
            $binary_data = base64_decode($base64_image_content);
            // 指定保存到本地的文件名和路径
            $file_name = 'sign'.time().rand(1000, 9999).".png";
            $file_path = $saveDir.'/'.date('Ymd').'/'.$file_name;
            $dir_name = dirname($file_path); // 获取目录路径
            if (!is_dir($dir_name)) {
                if (mkdir($dir_name, 0755, true)) {
                } else {
                    throw new \think\Exception("无法创建目录");
                }
            }

            // 将二进制数据写入文件
            if (!file_put_contents($file_path, $binary_data)) {
                throw new \think\Exception('签名上传失败');
            }

            // 4、写入数据库中
            $file = File::create([
                'cid'         => $cid,
                'type'        => FileEnum::IMAGE_TYPE,
                'name'        => $file_name,
                'uri'         => $file_path,
                'source_id'   => 0,
                'create_time' => time(),
            ]);

            // 5、返回结果
            return [
                'id'   => $file['id'],
                'cid'  => $file['cid'],
                'type' => $file['type'],
                'name' => $file['name'],
                'uri'  => FileService::getFileUrl($file['uri']),
                'url'  => $file['uri']
            ];

            //

        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * @notes 上传地址
     * @param $saveDir
     * @return string
     * @author dw
     * @date 2023/06/26
     */
    private static function getUploadUrl($saveDir):string
    {
        return $saveDir . '/' . date('Ymd');
    }


    /**
     *
     * @param $cid 文件分组ID la_file_cate的分组ID
     * @param int $sourceId 上传的用户ID
     * @param int $source 用户类型，SOURCE_USER
     * @return void
     * @author 林海涛
     * @date 2024/7/19 下午5:02
     */
    public static function uploadFies($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/file')
    {
        try{
            $data =[];
            $config = [
                'default' => ConfigService::get('storage', 'default', 'local'),
                'engine'  => ConfigService::get('storage') ?? [ 'local' => [] ],
            ];
            $files = request()->file('files');
            $limit = array_merge(config('project.file_image'), config('project.file_video'), config('project.file_file'));
            foreach($files as $file){
                if (!in_array(strtolower($file->extension()), $limit)) {
                    throw new Exception('不允许上传' . $file->extension() . '后缀文件');
                }
            }
            $insertData = [];
            $model = new File();
            $StorageDriver = new StorageDriver($config);
            foreach($files as $file)
            {
               $fileType = '';
                $saveDir = '';
               if (in_array(strtolower($file->extension()),  config('project.file_image'))) {
                   $fileType = FileEnum::IMAGE_TYPE;
                   $saveDir = 'uploads/images';
               } else if(in_array(strtolower($file->extension()),  config('project.file_video'))){
                   $fileType = FileEnum::VIDEO_TYPE;
                   $saveDir =  'uploads/video';
               } else if(in_array(strtolower($file->extension()),  config('project.file_video'))){
                   $fileType = FileEnum::FILE_TYPE;
                   $saveDir = 'uploads/file';
               }
               $StorageDriver->setUploadFile('files',$file->getOriginalName());
               $fileName = $StorageDriver->getFileName();
               $fileInfo = $StorageDriver->getFileInfo();
                $saveDir = self::getUploadUrl($saveDir);
               // 上传文件
               if (!$StorageDriver->upload($saveDir)) {
                   throw new Exception($StorageDriver->getError());
               }
               // 3、处理文件名称
               if (strlen($fileInfo['name']) > 128) {
                   $name = substr($fileInfo['name'], 0, 123);
                   $nameEnd = substr($fileInfo['name'], strlen($fileInfo['name']) - 5, strlen($fileInfo['name']));
                   $fileInfo['name'] = $name . $nameEnd;
               }
               $insertData[] = [
                   'cid'         => $cid,
                   'type'        => $fileType,
                   'name'        => $fileInfo['name'],
                   'uri'         => $saveDir . '/' . str_replace("\\", "/", $fileName),
                   'source'      => $source,
                   'source_id'   => $sourceId,
                   'create_time' => time(),
               ];
            }
            if(!empty($insertData)){
                $modelData = $model->saveAll($insertData);
                $data  = [];
                foreach($modelData as $v){
                    $data[] = [
                        'id'   => $v['id'],
                        'cid'  => $v['cid'],
                        'type' => $v['type'],
                        'name' => $v['name'],
                        'uri'  => FileService::getFileUrl($v['uri']),
                        'url'  => $v['uri']
                    ];
                }
            }
            return $data;
        }catch (\Exception $e){
            throw new Exception($e->getMessage());
        }
    }
}
