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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.backendsys.exception.CustException;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.upload.dao.SysFileCategoryDao;
import com.backendsys.modules.upload.dao.SysFileDao;
import com.backendsys.modules.upload.entity.SysFile;
import com.backendsys.modules.upload.entity.SysFileCategory;
import com.backendsys.modules.upload.service.SysFileCategoryService;
import com.backendsys.utils.response.ResultEnum;
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.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class SysFileCategoryServiceImpl implements SysFileCategoryService {

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private SysFileDao sysFileDao;
    @Autowired
    private SysFileCategoryDao sysFileCategoryDao;

    /**
     * 获取文件分类列表
     */
    @Override
    public Map<String, Object> selectUploadFileCategoryList(SysFileCategory sysFileCategory) {

        // [DB] 获得文件分类列表
        List<Map<String, Object>> list = sysFileCategoryDao.selectUploadFileCategoryList(sysFileCategory);
        // [DB] 获得文件总数量
        Long all_file_list_total = sysFileDao.selectCount(new LambdaQueryWrapper<SysFile>().eq(SysFile::getUser_id, sysFileCategory.getUser_id()));

        Map<String, Object> resp = new LinkedHashMap<>();
        resp.put("all_file_list_total", all_file_list_total);
        resp.put("list", list);
        return resp;
    }

    /**
     * 创建文件分类
     */
    @Override
    public Map<String, Object> insertFileCategory(SysFileCategory sysFileCategory) {

        Long total = sysFileCategoryDao.selectCount(new LambdaQueryWrapper<SysFileCategory>().eq(SysFileCategory::getUser_id, SecurityUtil.getUserId()));
        if (total > 20) throw new CustException("文件分类不能超过 20 个");

        sysFileCategoryDao.insert(sysFileCategory);
        return Map.of("id", sysFileCategory.getId());
    }

    /**
     * 编辑文件分类
     */
    @Override
    public Map<String, Object> updateFileCategory(SysFileCategory sysFileCategory) {
        sysFileCategoryDao.updateById(sysFileCategory);
        return Map.of("id", sysFileCategory.getId());
    }

//    /**
//     * 创建文件分类(批量)
//     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public Map<String, Object> insertFileCategoryBatch(List<SysFileCategory> sysFileCategoryList) {
//
//        // 是先删除当前用户ID下的全部记录，然后批量插入新数据
//        sysFileCategoryDao.delete(new LambdaQueryWrapper<SysFileCategory>().eq(SysFileCategory::getUser_id, SecurityUtil.getUserId()));
//        sysFileCategoryDao.insertBatch(sysFileCategoryList);
//
//        List<Long> ids = sysFileCategoryList.stream().map(item -> item.getId()).collect(Collectors.toList());
//        return Map.of("ids", ids);
//    }
//
//    /**
//     * 编辑文件分类(批量)
//     */
//    @Override
//    public Map<String, Object> updateFileCategoryBatch(List<SysFileCategory> sysFileCategoryList) {
//        sysFileCategoryDao.updateByIdBatch(sysFileCategoryList);
//        List<Long> ids = sysFileCategoryList.stream().map(item -> item.getId()).collect(Collectors.toList());
//        return Map.of("ids", ids);
//    }

    /**
     * 编辑文件分类(批量)(先删后增)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateFileCategoryBatch(List<SysFileCategory> sysFileCategoryList) {

        if (sysFileCategoryList.size() > 0) {
            sysFileCategoryList.stream().forEach(item -> {
                if (item.getCategory_name() != null && item.getCategory_name().isEmpty())
                    throw new CustException("文件分类名称不能为空");
                if (item.getCategory_name() != null && item.getCategory_name().length() > 50)
                    throw new CustException("文件分类名称长度不超过 50 字符");
                if (item.getSort() != null && (item.getSort() < 1 || item.getSort() > 9999))
                    throw new CustException("排序必须在 1 到 9999 之间");
                if (item.getStatus() != null && item.getStatus() != 1 && item.getStatus() != -1)
                    throw new CustException("状态取值有误，范围应是(-1禁用, 1启用)");
            });
        }

        // 获得当前用户ID
        Long user_id = SecurityUtil.getUserId();

        // 获得原文件分类列表 (用户的)
        SysFileCategory entity = new SysFileCategory();
        entity.setUser_id(user_id);
        List<Map<String, Object>> originList = sysFileCategoryDao.selectUploadFileCategoryList(entity);

        // 提取列表中的id集合作对比
        Set<Long> insertIdSet = new HashSet<>();
        Set<Long> originIdSet = originList.stream().map(item -> Convert.toLong(item.get("id"))).collect(Collectors.toSet());
        Set<Long> updateIdSet = sysFileCategoryList.stream().map(SysFileCategory::getId).collect(Collectors.toSet());
        Set<Long> updateIdSetNoNull = updateIdSet.stream().filter(id -> id != null && !id.toString().isEmpty()).collect(Collectors.toSet());
        Collection<Long> deleteIds = CollUtil.subtract(originIdSet, updateIdSet);

        Collection<Long> missingIds = CollUtil.subtract(updateIdSet, originIdSet);
        Collection<Long> missingIdsNoNull = missingIds.stream().filter(id -> id != null && !id.toString().isEmpty()).collect(Collectors.toSet());

//        System.out.println("------------------------------------");
//        System.out.println("originIdSet = " + originIdSet);
//        System.out.println("updateIdSet = " + updateIdSet);
//        System.out.println("deleteIds = " + deleteIds);
//        System.out.println("missingIds = " + missingIds);
//        System.out.println("missingIdsNoNull = " + missingIdsNoNull);
//        System.out.println("------------------------------------");

        String message = "";

        if (!missingIds.isEmpty()) {

            // 如果存在null，即是无id记录，则是新增
            List<SysFileCategory> insertListEntity = new ArrayList<>();
            for (SysFileCategory item : sysFileCategoryList) {
                Long id = item.getId();
                if (id == null) {
                    item.setUser_id(user_id);
                    insertListEntity.add(item);
                }
            }

            if (!insertListEntity.isEmpty()) {

                // 判断权限
                if (securityUtil.hasPermission("1.1.3")) new CustException(ResultEnum.AUTH_ROLE_ERROR.getMessage());
                // [DB] 批量新增
                sysFileCategoryDao.insertBatch(insertListEntity);

                StringBuilder insertIdSetStr = new StringBuilder();
                insertListEntity.stream().forEach(it -> {
                    if (it.getId() != null) {
                        insertIdSet.add(it.getId());
                        if (insertIdSetStr.length() > 0) {
                            insertIdSetStr.append(", ");
                        }
                        insertIdSetStr.append(Convert.toStr(it.getId()));
                    }
                });
                message += "新增了 Id: " + insertIdSetStr + " 等, ";
            }

            // 如果有多出的ID，则抛出异常 (过滤空值)
            if (!missingIdsNoNull.isEmpty()) {
                String missingIdsStr = missingIdsNoNull.stream().map(String::valueOf).collect(Collectors.joining(", "));
                throw new CustException("id: " + missingIdsStr + ", 不存在");
            }
        }

        // 如果有缺少的ID，则是删除
        if (!deleteIds.isEmpty()) {
            // 判断每个分类下已绑定的文件是否为空，不空的分类不允许删除
            for (Map<String, Object> item : originList) {
                Long id = Convert.toLong(item.get("id"));
                Long category_file_count = Convert.toLong(item.get("category_file_count"));
                if (deleteIds.contains(id)) {
                    if (category_file_count == null || category_file_count != 0) {
                        throw new CustException("id: " + id + ", 需要清除文件后才可删除");
                    }
                }
            }

            // 判断权限
            if (securityUtil.hasPermission("1.1.6")) new CustException(ResultEnum.AUTH_ROLE_ERROR.getMessage());
            // [DB] 批量删除
            sysFileCategoryDao.deleteBatchIds(deleteIds);
            
            
            // [DB] 查询判断数量如果大于20，则更新失败
            Long total = sysFileCategoryDao.selectCount(new LambdaQueryWrapper<SysFileCategory>().eq(SysFileCategory::getUser_id, user_id));
            if (total > 20) throw new CustException("文件分类不能超过 20 个");


            String deleteIdsStr = deleteIds.stream().map(String::valueOf).collect(Collectors.joining(", "));
            message += "删除了 Id: " + deleteIdsStr + ", ";
        }



        if (sysFileCategoryList.size() > 0) {

            // 判断权限
            if (securityUtil.hasPermission("1.1.4")) new CustException(ResultEnum.AUTH_ROLE_ERROR.getMessage());
            // [DB] 批量更新
            sysFileCategoryDao.updateByIdBatch(sysFileCategoryList);

            String updateIdSetStr = updateIdSetNoNull.stream().map(String::valueOf).collect(Collectors.joining(", "));
            message += "更新了 Id: " + updateIdSetStr;
        }

        // 返回值
        Map<String, Object> response = new LinkedHashMap<>();
        response.put("message", message);
        response.put("insert_ids", insertIdSet);
        response.put("delete_ids", deleteIds);
        response.put("update_ids", updateIdSetNoNull);
        return response;
    }

    /**
     * 删除文件分类
     */
    @Override
    public Map<String, Object> deleteFileCategory(SysFileCategory sysFileCategory) {

        // 判断分类下是否有文件，有则不能删除
        Long count = sysFileDao.selectCount(new LambdaQueryWrapper<SysFile>().eq(SysFile::getCategory_id, sysFileCategory.getId()));
        if (count > 0) {
            throw new CustException("该分类下存在文件，请先移动或删除文件后操作");
        }

        LambdaQueryWrapper<SysFileCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysFileCategory::getId, sysFileCategory.getId());
        wrapper.eq(SysFileCategory::getUser_id, sysFileCategory.getUser_id());
        sysFileCategoryDao.delete(wrapper);
        return Map.of("id", sysFileCategory.getId());
    }


}
