package com.backendsys.modules.material.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.backendsys.exception.CustException;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.material.dao.MaterialCategoryDao;
import com.backendsys.modules.material.dao.MaterialDao;
import com.backendsys.modules.material.dao.MaterialTagDao;
import com.backendsys.modules.material.entity.Material;
import com.backendsys.modules.material.entity.MaterialCategory;
import com.backendsys.modules.material.entity.MaterialTag;
import com.backendsys.modules.material.service.MaterialService;
import com.backendsys.modules.system.entity.SysUserRole;
import com.backendsys.modules.system.service.SysUserRoleService;
import com.backendsys.modules.upload.service.SysFileService;
import com.backendsys.modules.upload.utils.ObjectKey.ObjectKeyEntity;
import com.backendsys.modules.upload.utils.ObjectKey.ObjectKeyUtil;
import com.backendsys.modules.upload.utils.UploadUtil;
import com.backendsys.utils.response.PageEntity;
import com.backendsys.utils.response.PageInfoResult;
import com.backendsys.utils.v2.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class MaterialServiceImpl implements MaterialService {

    @Autowired
    private ObjectKeyUtil objectKeyUtil;

    @Autowired
    private MaterialDao materialDao;
    @Autowired
    private MaterialTagDao materialTagDao;
    @Autowired
    private MaterialCategoryDao materialCategoryDao;
    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private SysUserRoleService sysUserRoleService;

    private List<MaterialTag> getMaterialTagByIds(String tag_ids) {
        if (StrUtil.isEmpty(tag_ids)) return null;
        LambdaQueryWrapper<MaterialTag> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(MaterialTag::getId, tag_ids.split(","));
        wrapper.orderByDesc(MaterialTag::getSort);
        return materialTagDao.selectList(wrapper);
    }

    /**
     * 获取素材列表
     */
    @Override
    public PageEntity selectMaterialList(Material material) {
        PageUtils.startPage();  // 分页

        List<Map<String, Object>> list = materialDao.selectMaterialList(material);

        // 1) 完成分页实体渲染
        PageEntity pageEntity = new PageInfoResult(list).toEntity();

        if (!list.isEmpty()) {
            // 2) 分页列表格式化
            list = list.stream().map(item -> {
                // 新增字段：标签列表
                String tag_ids = Convert.toStr(item.get("tag_ids"));
                List<MaterialTag> materialTagList = getMaterialTagByIds(tag_ids);
                item.put("tag_list", materialTagList);
                return item;
            }).collect(Collectors.toList());

            // 3) 分页实体重新赋值
            List<Object> objectList = list.stream().map(item -> (Object) item).collect(Collectors.toList());
            pageEntity.setList(objectList);
        }

        return pageEntity;
    }

    /**
     * 获取素材详情
     */
    @Override
    public Material selectMaterialDetail(Material material) {

        Material detail = materialDao.selectMaterialDetail(material);
        if (detail == null) throw new CustException("素材不存在");

        // [新增字段] 标签列表
        List<MaterialTag> materialTagList = getMaterialTagByIds(detail.getTag_ids());
        detail.setTag_list(materialTagList);

        // [DB] 查询当前用户角色，如果是素材游客，则不显示图片
        List<SysUserRole> role_list = sysUserRoleService.selectUserRoleByUserId(SecurityUtil.getUserId());
        AtomicReference<Boolean> hasPermission = new AtomicReference<>(false);
        role_list.stream().forEach(role -> {
            if ("MATERIAL_USER".equals(role.getRole_sign()) || "MATERIAL_ADMIN".equals(role.getRole_sign())) {
                hasPermission.set(true);
            }
        });

        // 如果当前用户没有权限，则不显示图片
        if (!hasPermission.get()) {
            detail.setFile_url("Unauthorized");
            detail.setPan_baidu_url("Unauthorized");
        }

        return detail;
    }

    /**
     * 创建素材
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> insertMaterial(Material material) {

        MaterialCategory materialCategory = materialCategoryDao.selectById(material.getCategory_id());
        if (materialCategory == null) throw new CustException("素材分类不存在");

        // [Filter] tag_id 过滤掉空值和 0
        String cleaned = Optional.ofNullable(material.getTag_ids())
            .orElse("")
            .replaceAll("\\b0\\b,?", "")
            .replaceAll(",{2,}", ",")
            .replaceAll("^,|,$", "");
        material.setTag_ids(cleaned);

        // 生成缩略图，并填充缩略图地址
        if (StrUtil.isNotEmpty(material.getImage_url())) {
            ObjectKeyEntity objectKeyEntity = objectKeyUtil.urlToObjectKey(material.getImage_url());
            if (objectKeyEntity != null) {
                String image_thumb_url = UploadUtil.getImageThumbUrl(material.getImage_url(), objectKeyEntity.getTarget(), 276, 155);
                material.setImage_thumb_url(image_thumb_url);
            }
        }

        materialDao.insertMaterial(material);

        return Map.of("material_id", material.getMaterial_id());
    }

    /**
     * 编辑素材
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateMaterial(Material material) {

        Material detail = materialDao.selectById(material.getMaterial_id());
        if (detail == null) throw new CustException("素材不存在");

        if (material.getCategory_id() != null) {
            MaterialCategory materialCategory = materialCategoryDao.selectById(material.getCategory_id());
            if (materialCategory == null) throw new CustException("素材分类不存在");
        }

        // [Filter] tag_id 过滤掉空值和 0
        String cleaned = Optional.ofNullable(material.getTag_ids())
            .orElse("")
            .replaceAll("\\b0\\b,?", "")
            .replaceAll(",{2,}", ",")
            .replaceAll("^,|,$", "");
        material.setTag_ids(cleaned);

        // 编辑的时候，如果素材图片有修改，需要删除之前的图片

        // 生成缩略图，并填充缩略图地址
        if (StrUtil.isNotEmpty(material.getImage_url())) {
            ObjectKeyEntity objectKeyEntity = objectKeyUtil.urlToObjectKey(material.getImage_url());
            if (objectKeyEntity != null) {
                String image_thumb_url = UploadUtil.getImageThumbUrl(material.getImage_url(), objectKeyEntity.getTarget(), 276, 155);
                material.setImage_thumb_url(image_thumb_url);
            }
        }

        materialDao.updateMaterial(material);
        return Map.of("material_id", material.getMaterial_id());
    };

    /**
     * 删除素材
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> deleteMaterial(Material material) {

        Material detail = materialDao.selectById(material.getMaterial_id());
        if (detail == null) throw new CustException("素材不存在");

        // 删除的时候，同时删除对象存储中的素材图片 (异步)
        ObjectKeyEntity image_url_object = objectKeyUtil.urlToObjectKey(detail.getImage_url());
        ObjectKeyEntity file_url_object = objectKeyUtil.urlToObjectKey(detail.getFile_url());
        CompletableFuture.runAsync(() -> {
            sysFileService.deleteObject(image_url_object.getObject_key(), image_url_object.getTarget());
            sysFileService.deleteObject(file_url_object.getObject_key(), file_url_object.getTarget());
        });

        materialDao.deleteMaterial(material);
        return Map.of("material_id", material.getMaterial_id());
    }

}
