<?php
declare (strict_types=1);

namespace app\api\controller;

use app\adminapi\model\material\Material;
use app\common\service\FileService;
use app\common\service\storage\StorageFactory;
use core\base\BaseApiController;

/**
 * @OA\Tag(
 *     name="公共",
 *     description="通用文件上传接口"
 * )
 */
class UploadController extends BaseApiController
{
    /**
     * @OA\Post(
     *     path="/upload/upload",
     *     summary="文件上传",
     *     tags={"公共"},
     *     @OA\RequestBody(
     *         required=true,
     *         @OA\MediaType(
     *             mediaType="multipart/form-data",
     *             @OA\Schema(
     *                 required={"file"},
     *                 @OA\Property(property="file", type="string", format="binary", description="上传文件"),
     *             )
     *         )
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="成功响应",
     *         @OA\JsonContent(
     *             @OA\Property(property="code", type="integer", example=1),
     *             @OA\Property(property="msg", type="string", example="上传成功"),
     *             @OA\Property(
     *                 property="data",
     *                 type="object",
     *                 @OA\Property(property="key", type="string", example="material/20260128/xxx.png", description="相对路径"),
     *                 @OA\Property(property="url", type="string", example="/storage/material/20260128/xxx.png", description="访问链接"),
     *                 @OA\Property(property="type", type="string", example="image", description="文件类型"),
     *                 @OA\Property(property="size", type="integer", example=12345, description="文件大小"),
     *                 @OA\Property(property="name", type="string", example="原始文件名.png", description="原始文件名")
     *             )
     *         )
     *     )
     * )
     */
    public function upload()
    {
        $file = $this->request->file('file');
        if (!$file) {
            return fail('file is required');
        }

        $originName = (string)$file->getOriginalName();
        $size = (int)$file->getSize();
        $mime = method_exists($file, 'getMime') ? (string)$file->getMime() : '';

        $type = $this->detectType($originName, $mime);

        $maxSize = (int)config('storage.max_size', 0);
        if ($maxSize > 0 && $size > $maxSize) {
            return fail('file size exceeds limit');
        }

        try {
            $storage = StorageFactory::create();
            $saved = $storage->put($file, 'material');
        } catch (\Throwable $e) {
            return fail($e->getMessage());
        }

        $data = [
            'type' => $type,
            'storage' => (string)config('storage.default', 'local'),
            'name' => $originName,
            'ext' => strtolower(pathinfo($originName, PATHINFO_EXTENSION)),
            'mime' => $mime,
            'size' => $size,
            'path' => $saved['key'],
            'url' => $saved['url'],
            'create_time' => time(),
        ];
        (new Material())->save($data);

        return success('上传成功', [
            'key' => $saved['key'],
            'url' => FileService::getFileUrl(trim($saved['url'], '/')),
            'type' => $type,
            'size' => $size,
            'name' => $originName,
        ]);
    }

    protected function detectType(string $name, string $mime = ''): string
    {
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
        if (in_array($ext, ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'], true)) {
            return 'image';
        }
        if (in_array($ext, ['mp4', 'mov', 'avi', 'mkv', 'wmv', 'flv', 'webm'], true)) {
            return 'video';
        }
        if ($mime !== '') {
            if (str_starts_with($mime, 'image/')) {
                return 'image';
            }
            if (str_starts_with($mime, 'video/')) {
                return 'video';
            }
        }
        return 'file';
    }
}
