<?php
namespace app\adminapi\service\material;

use core\base\BaseService;
use app\adminapi\model\material\Material;
use app\adminapi\model\material\MaterialCategory;
use app\common\service\storage\StorageFactory;
use app\common\service\storage\StorageInterface;

/**
 * 素材服务（上传/列表/删除/移动）
 */
class MaterialService extends BaseService
{
    public function __construct()
    {
        parent::__construct();
        $this->model = new Material();
    }

    protected function storage(): StorageInterface
    {
        return StorageFactory::create();
    }

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

    public function add(array $params): array
    {
        $file = $this->request->file('file');
        if (!$file) throw new \RuntimeException('请上传文件');

        $categoryId = (int)($params['category_id'] ?? 0);
        if ($categoryId > 0 && !(new MaterialCategory())->where('id', $categoryId)->find()) {
            throw new \RuntimeException('分类不存在');
        }

        $originName = $file->getOriginalName();
        $size = (int)$file->getSize();
        $mime = method_exists($file, 'getMime') ? (string)$file->getMime() : '';
        $type = (string)($params['type'] ?? '');
        $type = $type ?: $this->detectType($originName, $mime);

        $storage = $this->storage();
        $saved = $storage->put($file, 'material');

        $data = [
            'category_id' => $categoryId,
            '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(),
            'key' => $saved['key']
        ];
        $this->model->save($data);
        $data['id'] = $this->model->id;

        return $data;
    }

    public function lists(array $params): array
    {
        $where = [];
        if (!empty($params['type']) && $params['type'] !== 'file') {
            $where[] = ['type', '=', $params['type']];
        }
        if (!empty($params['category_id'])) {
            $where[] = ['category_id', '=', (int)$params['category_id']];
        }
        if (!empty($params['keyword'])) {
            $where[] = ['name', 'like', '%' . $params['keyword'] . '%'];
        }

        $query = $this->model
            ->where($where)
            ->field('id,category_id,type,name,url,create_time')
            ->order('id desc');

        $list = $this->pageQuery($query, function ($item) {
            return $item;
        });

        return $list;
    }

    public function detail(int $id): array
    {
        $row = $this->model
            ->where('id', $id)
            ->field('id,category_id,type,name,url,create_time')
            ->find();
        if (!$row) throw new \RuntimeException('素材不存在');
        $data = $row->toArray();
        return $data;
    }

    public function delete($id): void
    {
        $ids = is_array($id) ? $id : [$id];
        if (empty($ids)) {
            throw new \RuntimeException('请选择要删除的素材');
        }

        // 获取要删除的素材信息
        $materials = $this->model->whereIn('id', $ids)->select();
        if ($materials->isEmpty()) {
            throw new \RuntimeException('素材不存在');
        }

        // 检查是否所有ID都存在
        if (count($materials) !== count($ids)) {
            throw new \RuntimeException('部分素材不存在');
        }

        try {
            // 开启事务
            $this->model->startTrans();

            // 删除数据库记录
            $this->model->whereIn('id', $ids)->delete();

            // 删除物理文件
            foreach ($materials as $material) {
                $data = $material->toArray();
                $driver = (string)($data['storage'] ?? config('storage.default', 'local'));
                $storage = StorageFactory::create($driver);
                
                try {
                    $storage->delete((string)$data['path']);
                } catch (\Exception $e) {
                    // 文件删除失败不影响数据库删除，只记录日志
                    trace_log('素材文件删除失败: ' . $data['path'] . ', 错误: ' . $e->getMessage());
                }
            }

            // 提交事务
            $this->model->commit();
        } catch (\Exception $e) {
            // 回滚事务
            $this->model->rollback();
            throw new \RuntimeException('删除失败：' . $e->getMessage());
        }
    }

    public function move(array $id, int $categoryId): void
    {
        if ($categoryId > 0 && !(new MaterialCategory())->where('id', $categoryId)->find()) {
            throw new \RuntimeException('分类不存在');
        }
        $id = array_values(array_filter(array_map('intval', $id), fn($v) => $v > 0));
        if (!$id) throw new \RuntimeException('请选择要移动的素材');

        $this->model->whereIn('id', $id)->update([
            'category_id' => $categoryId,
            'update_time' => time(),
        ]);
    }
}
