package com.huigou.topsun.resource.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huigou.topsun.resource.domain.ResourceType;
import com.huigou.topsun.resource.mapper.ResourceTypeMapper;
import com.huigou.topsun.resource.service.ResourceFiledService;
import com.huigou.topsun.resource.service.ResourceTypeService;
import com.huigou.topsun.util.PinyinHelperUtil;
import com.huigou.topsun.resource.vo.ResourceFiledVo;
import com.huigou.topsun.resource.vo.ResourceTypeTreeVo;
import com.huigou.topsun.resource.vo.ResourceTypeVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 16508
 * @description 针对表【resource_type(资源分类)】的数据库操作Service实现
 * @createDate 2023-10-25 16:08:43
 */
@Service
public class ResourceTypeServiceImpl extends ServiceImpl<ResourceTypeMapper, ResourceType>
        implements ResourceTypeService {
    @Resource
    private ResourceTypeMapper resourceTypeMapper;
    @Resource
    private ResourceFiledService resourceFiledService;

    @Transactional
    @Override
    public ResourceTypeVo saveResourceTypeMain(ResourceTypeVo resourceTypeVo) {
        if (!StringUtils.isEmpty(resourceTypeVo.getResourceTableTitle())) {
            String tableName = PinyinHelperUtil.getPinYinHeadChar(resourceTypeVo.getResourceTableTitle());
            resourceTypeVo.setResourceTableName("res_" + tableName);
        }
        ResourceType resourceType = ResourceTypeVo.getResourceType(resourceTypeVo);
        this.save(resourceType);
        resourceTypeVo.setResourceTypeId(resourceType.getResourceTypeId());
        List<ResourceFiledVo> resourceFileds = resourceTypeVo.getResourceFileds();
        List<String> fieldList = new ArrayList<>();
        for (int i = 0; i < resourceFileds.size(); i++) {
            ResourceFiledVo resourceFiled = resourceFileds.get(i);
            resourceFiled.setResourceTypeId(resourceType.getResourceTypeId());
            resourceFiled.setResourceFieldId(null);
            //字段名称首字母小写
            String pinYinHeadChar = PinyinHelperUtil.getPinYinHeadChar(resourceFiled.getResourceFiledTitle());
            if (fieldList.indexOf(pinYinHeadChar) > 0) {
                //如果首字母小写重复，则加入下划线+下标
                pinYinHeadChar = pinYinHeadChar + "_" + i;
            }
            fieldList.add(pinYinHeadChar);
            resourceFiled.setResourceFieldName(pinYinHeadChar);
            //如果字段的长度、小数点为null，设置默认值
            if ("string".equals(resourceFiled.getResourceFieldType())){
                resourceFiled.setResourceFieldSize(resourceFiled.getResourceFieldSize() == null ? 255 : resourceFiled.getResourceFieldSize());
            }
            if ("float".equals(resourceFiled.getResourceFieldType())
                    || "double".equals(resourceFiled.getResourceFieldType())){
                resourceFiled.setIntegerLength(resourceFiled.getIntegerLength() == null ? 10 : resourceFiled.getIntegerLength());
                resourceFiled.setDecimalPrecision(resourceFiled.getDecimalPrecision() == null ? 2 : resourceFiled.getDecimalPrecision());
            }

            ResourceFiledVo resourceFiledVo = resourceFiledService.saveResourceFiled(resourceFiled);
            resourceFiled.setResourceFieldId(resourceFiledVo.getResourceFieldId());
        }
        //创建表
        resourceFiledService.createTable(resourceFileds, resourceTypeVo.getResourceTableName(), resourceTypeVo.getResourceTableTitle());
        return resourceTypeVo;
    }

    @Transactional
    @Override
    public ResourceTypeVo updateResourceTypeMain(ResourceTypeVo resourceTypeVo) {
        //先获取到数据库资源表配置字段
        this.updateById(ResourceTypeVo.getResourceType(resourceTypeVo));
        List<ResourceFiledVo> resourceFileds = resourceTypeVo.getResourceFileds();

        List<ResourceFiledVo> dbFiledVoList = resourceFiledService.findByResourceTypeId(resourceTypeVo.getResourceTypeId());
        //先根据资源类型id删除字段，再保存
        resourceFiledService.deleteByResourceTypeId(resourceTypeVo.getResourceTypeId());

        this.dealResourceFileds(resourceFileds,dbFiledVoList, resourceTypeVo.getResourceTableName());
        for (ResourceFiledVo resourceFiledVo : resourceFileds) {
            //字段名称首字母小写
            String pinYinHeadChar = PinyinHelperUtil.getPinYinHeadChar(resourceFiledVo.getResourceFieldName());
            resourceFiledVo.setResourceFieldName(pinYinHeadChar);
            resourceFiledVo.setResourceTypeId(resourceTypeVo.getResourceTypeId());
            resourceFiledService.saveResourceFiled(resourceFiledVo);
        }
        //更新表
        return resourceTypeVo;
    }

    @Transactional
    public void dealResourceFileds(List<ResourceFiledVo> resourceFileds,List<ResourceFiledVo> dbFiledVoList, String tableName) {
        if (resourceFileds.isEmpty()) {
            //添加新增的所有字段（id除外）
            resourceFiledService.updateTableAddColumn(resourceFileds, tableName);
        } else {
            Set<ResourceFiledVo> resourceFiledSet = new HashSet<>();
            Set<ResourceFiledVo> resourceFiledChangeSet = new HashSet<>();
            for (ResourceFiledVo resourceFiledVo : resourceFileds) {
                String pinYinHeadChar = PinyinHelperUtil.getPinYinHeadChar(resourceFiledVo.getResourceFiledTitle());
                resourceFiledVo.setResourceFieldName(pinYinHeadChar);
                if (resourceFiledVo.getResourceFieldId() != null) {//如果id不为空，更新字段
                    for (ResourceFiledVo dbFiledVo : dbFiledVoList) {
                        if (resourceFiledVo.getResourceFieldId().equals(dbFiledVo.getResourceFieldId())){
                            resourceFiledVo.setDbResourceFieldName(dbFiledVo.getResourceFieldName());
                        }
                    }
                    resourceFiledChangeSet.add(resourceFiledVo);
                } else {
                    resourceFiledSet.add(resourceFiledVo);//id 为null则是新增的字段，添加
                }
            }
            //新增字段
            if (!CollectionUtils.isEmpty(resourceFiledSet)){
                List<ResourceFiledVo> resourceFiledList = new ArrayList<>(resourceFiledSet);
                resourceFiledService.updateTableAddColumn(resourceFiledList, tableName);
            }

            //修改字段
            if (!CollectionUtils.isEmpty(resourceFiledChangeSet)){
                List<ResourceFiledVo> resourceFiledChangeList = new ArrayList<>(resourceFiledChangeSet);
                resourceFiledService.updateTableChangeColumn(resourceFiledChangeList,tableName);
            }
        }
    }


    @Override
    public void deleteById(String id) {
        ResourceType resourceType = this.getById(id);
        resourceFiledService.deleteByResourceTypeId(id);
        resourceTypeMapper.deleteById(id);
        resourceFiledService.dropTableByResourceName(resourceType.getResourceTableName());
    }

    @Override
    public ResourceTypeVo findById(String id) {
        return ResourceTypeVo.getResourceTypeVo(this.getById(id));
    }

    @Override
    public List<ResourceTypeVo> findList() {
        return resourceTypeMapper.noteTree();
    }

    @Override
    public ResourceTypeVo findByTableName(String tableName){
        LambdaQueryWrapper<ResourceType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ResourceType::getResourceTableName,tableName);
        return ResourceTypeVo.getResourceTypeVo(this.getOne(queryWrapper));
    }

    @Override
    public List<ResourceFiledVo> findParentResourceFileds(String tableName) {
        Set<ResourceFiledVo> resourceFileds = new HashSet<>();
        findParentMenusRecursively(tableName, resourceFileds);
        List<ResourceFiledVo> filedVos = resourceFileds
                .stream()
                .sorted(Comparator.comparing(ResourceFiledVo::getSortNum))
                .collect(Collectors.toList());
        return filedVos;
    }

    @Override
    public void findParentMenusRecursively(String tableName, Set<ResourceFiledVo> resourceFileds) {
        ResourceTypeVo resourceTypeVo = this.findByTableName(tableName);
        if (resourceTypeVo != null) {
            List<ResourceFiledVo> resourceFiledList = resourceFiledService.findByResourceTypeId(resourceTypeVo.getResourceTypeId());
            List<String> filedNames = resourceFileds
                    .stream()
                    .map(ResourceFiledVo::getResourceFieldName).collect(Collectors.toList());

            if (CollectionUtils.isEmpty(resourceFileds)){
                resourceFileds.addAll(resourceFiledList);
            }else {
                for (ResourceFiledVo resourceFiledVo : resourceFiledList) {
                    if (!filedNames.contains(resourceFiledVo.getResourceFieldName())){
                        resourceFileds.add(resourceFiledVo);
                    }
                }
            }
            String parentTableName = resourceTypeVo.getParentTableName();
            if (parentTableName != null) {
                findParentMenusRecursively(parentTableName, resourceFileds);
            }
        }
    }

    @Override
    public ResourceTypeVo initResourceTypeVo(String tableName) {
        ResourceTypeVo resourceTypeVo = new ResourceTypeVo();
        ResourceTypeVo parentResourceType = this.findByTableName(tableName);
        resourceTypeVo.setParentTableName(parentResourceType.getResourceTableName());
        resourceTypeVo.setParentTableTitle(parentResourceType.getResourceTableTitle());
        resourceTypeVo.setSuperTableName(parentResourceType.getParentTableName());
        resourceTypeVo.setSuperTableTitle(parentResourceType.getParentTableTitle());
        return resourceTypeVo;
    }

    @Override
    public List<ResourceFiledVo> findResourceTypeFields(String tableName) {
        List<ResourceFiledVo> resourceFileds = this.findParentResourceFileds(tableName);
        return resourceFileds;
    }

    @Override
    public List<ResourceTypeTreeVo> queryResourceTypes(String parentTableName) {
        return resourceTypeMapper.queryResourceTypes(parentTableName);
    }
}




